Codeforces India Hack2016 653ABCED

来源:互联网 发布:诽谤方志敏网络文章 编辑:程序博客网 时间:2024/05/17 18:47

Codeforces India Hack2016 653ABCED
通过数:2
Rating:1288
倒数第二题是后缀数组,倒数第一题没看,哪一天再厉害一点再做吧。

A:
简单题

#include <bits/stdc++.h>using namespace std;#define pb push_backconst int MAXN = 1000 + 5;int a[MAXN], n;vector<int>vc;int main(){    while(scanf("%d", &n) != EOF) {        for(int i = 0 ; i < n ; i++) scanf("%d", a + i);        sort(a, a + n);        for(int i = 0 ; i < n ; i++) vc.pb(a[i]);        vector<int>::iterator newend = unique(vc.begin(), vc.end());        vc.erase(newend, vc.end());        int ok = 0;        for(int i = 0 ; i < (int)vc.size() ; i++) {            if(i < 2) continue;            if(vc[i - 2] == vc[i] - 2 && vc[i - 1] == vc[i] - 1) {                ok = 1;                break;            }        }        if(ok) puts("YES");        else puts("NO");    }    return 0;}

B:

#include <bits/stdc++.h>using namespace std;const int MAXN = 26;#define pb push_backvector<int>e[MAXN + 5];int H, m;char s1[MAXN], s2[MAXN];int ans;void dfs(int u, int dep){    if(dep == H) {        ans++;        return;    }    for(int i = 0 ; i < (int)e[u].size() ; i++) {        dfs(e[u][i], dep + 1);    }}int main(){    while(scanf("%d%d", &H, &m) != EOF) {        for(int i = 0 ; i < MAXN ; i++) e[i].clear();        for(int i = 0 ; i < m ; i++) {            scanf("%s%s", s1, s2);            e[s2[0] - 'a'].pb(s1[0] - 'a');        }        ans = 0;        dfs(0, 1);        printf("%d\n", ans);    }    return 0;}

C:
/*
最多有几个不合法点是有限的,大约4-6个
然后在这些不合法的点里,枚举它和其余点交换的情况
交换后,最多影响6个点,看一看这6个点是否合法,合法后是否6个受影响的点覆盖了原不合法的点集
*/

#include <bits/stdc++.h>using namespace std;#define pb push_backconst int MAXN = 150000 + 5;int a[MAXN], n;vector<int>vc, e;bool invc[MAXN];bool valid(int u){    if(u == n) return true;    else if(u % 2 == 1 && a[u] >= a[u + 1]) return false;    else if(u % 2 == 0 && a[u] <= a[u + 1]) return false;    return true;}int solve(int mark, int i){    swap(a[i], a[vc[mark]]);    int ok = 1;    if(!valid(i)) ok = 0;  // printf("i = %d, first ok = %d\n", i, ok);    if(i > 1 && !valid(i - 1)) ok = 0;// printf("i = %d, second ok = %d\n", i, ok);    if(!valid(vc[mark])) ok = 0;// printf("i = %d, third ok = %d\n", i, ok);    if(vc[0] > 1 && !valid(vc[mark] - 1)) ok = 0;// printf("i = %d, forth ok = %d\n", i, ok);//    puts("");    if(ok) {        if(!e.empty()) e.clear();        for(int j = -1 ; j <= 1 ; j++) {            e.pb(vc[mark] + j);            e.pb(i + j);        }        sort(e.begin(), e.end());        vector<int>::iterator newend = unique(e.begin(), e.end());        e.erase(newend, e.end());        int now = 0;        for(int j = 0 ; j < (int)e.size() ; j++) {            if(now == vc.size()) break;            if(vc[now] == e[j]) now++;        }        if(now < vc.size()) ok = 0;    }    swap(a[i], a[vc[mark]]);    return ok;}int main(){    while(scanf("%d", &n) != EOF) {        if(!vc.empty()) vc.clear();        for(int i = 1 ; i <= n ; i++) scanf("%d", a + i);        memset(invc, false, sizeof invc);        for(int i = 1 ; i < n ; i++) {            if(!valid(i)) {                vc.pb(i); vc.pb(i + 1);                invc[i] = true; invc[i + 1] = true;            }        }        sort(vc.begin(), vc.end());        vector<int>::iterator newend = unique(vc.begin(), vc.end());        vc.erase(newend, vc.end());//        for(int i = 0 ; i < (int)vc.size() ; i++) printf("%d ", vc[i]);//        printf("\n");        if(vc.size() > 6) puts("0");    ///此处若写为4则WA        else {            int ans = 0;            for(int mark = 0 ; mark < vc.size() ; mark++) {                for(int i = 1 ; i <= n ; i++) {                   if(invc[i]) continue;                   if(solve(mark, i)) ans++;                }            }            for(int mark = 0 ; mark < vc.size() ; mark++) {                for(int j = mark + 1; j < vc.size() ; j++) {                    if(solve(mark, vc[j])) ans++;                }            }            printf("%d\n", ans);        }    }    return 0;}

D:
/*
二分快递员的载重量,然后可以知道每条边可以通行几个快递员
然后跑一遍网络流

值得注意的是最后二分判断的时候用了循环次数而不是左右端点的差值大小来作为循环结束的条件实现了二分次数的可控,同时保证了精度

*/

#include <bits/stdc++.h>using namespace std;#define LL long long#define pb push_back#define mp make_pair#define fi first#define se second#define inf (1000000007)#define gmin(a,b) ((a) < (b) ? (a) : (b))#define gmax(a,b) ((a) > (b) ? (a) : (b))typedef pair<int,LL> pii;const int MAXN = 50 + 5;const int MAXM = 500 + 5;const double eps = 1e-10;vector<pii>e[MAXN];int n, m, x;LL num[MAXN];queue<int>que;int s, t;                       ///源点、汇点int d[MAXN], vis[MAXN];         ///距起点距离,访问数组int cnt;int head[MAXN];struct Edge                     ///此邻接表少add_edge函数,需要自己添加{    int v, flow, ne;            ///用flow表示残量    Edge(){}    Edge(int _u, int _v, int _flow){v = _v, ne = head[_u]; flow = _flow;}}edge[MAXM * 2];void addedge(int u, int v, int w){    edge[cnt] = Edge(u, v, w);    head[u] = cnt++;    edge[cnt] = Edge(v, u, 0);    head[v] = cnt++;}bool BFS(int s, int t){    memset(vis, 0, sizeof(vis));    while(!que.empty()) que.pop();    vis[s] = 1;    d[s] = 0;    que.push(s);    while(!que.empty()){        int u = que.front();  que.pop();//        printf("u = %d\n", u);        for(int now = head[u] ; now != -1 ; now = edge[now].ne){            int v = edge[now].v;            if(!vis[v] && edge[now].flow > 0){                vis[v] = 1;                d[v] = d[u] + 1;                que.push(v);            }        }    }    return vis[t];}int DFS(int u, int a){//    printf("u = %d, a = %d\n", u, a);    if(u == n || a == 0)        return a;    int flow = 0, f;    for(int now = head[u] ; now != -1 ; now = edge[now].ne){        int v = edge[now].v;        if(d[v] == d[u] + 1 && (f = DFS(v, min(edge[now].flow, a)))){   ///用DFS来回溯对边进行操作            edge[now].flow -= f;            edge[now ^ 1].flow += f;            flow += f;            a -= f;            if(a == 0)  break;        }    }    return flow;}int Dinic()                                                     ///求最大流{    int ans = 0;    while(BFS(s, t)){        ans += DFS(s, inf);                                     ///进入起点时,设初始流量无限大    }    return ans;}inline bool check(double v){    s = 1, t = n;    cnt = 0;    memset(head, -1, sizeof head);    for(int i = 1 ; i <= n ; i++) {        for(int j = 0 ; j < (int)e[i].size() ; j++) {            pii p = e[i][j];            LL temp = p.se / v;//            if(temp < 0) printf("v = %f, i = %d, temp = %f\n", v, i, temp);            int tmp = gmin(temp, inf);            addedge(i, p.fi, tmp);        }    }    int temp = Dinic();//    printf("v = %f, temp = %d\n", v, temp);    if(temp >= x) return true;    else return false;}int main(){    while(scanf("%d%d%d", &n, &m, &x) != EOF) {        for(int i = 1 ; i <= n ; i++) e[i].clear();        int u, v;        LL w;        for(int i = 0 ; i < m ; i++) {            scanf("%d%d%I64d", &u, &v, &w);            e[u].pb(mp(v, w));        }        double left = 0, right = 1000000 + 1;        for(int i = 0 ; i < 200 ; i++) {            double mid = (right + left) / 2;            if(check(mid)) left = mid;            else right = mid;        }        printf("%.8f\n", right * x);    }    return 0;}

E:
/*
基本抄标程
已经想到要在补图上做dfs,然后判断有几个连通子块是必须要通过节点1与全图连通的就可以
但是由于补图实在太过巨大不知道怎么处理*
标程给出一种十分简便优越做法
存储一个名叫remain的set,表示剩余的点集
每次查找remain里的点,与当前点是否有不可以相连的边
没有则算入下一次dfs的储备对象里,并且从remain中删除该节点
为了防止边访问边删除导致set出现错误的情况,先用一个临时的结构存储所有可能点,然后从结构中调用该点进行删除
*/

#include <bits/stdc++.h>using namespace std;#define pb push_back#define mp make_pairconst int MAXN = 300000 + 5;typedef pair<int,int> pii;set<pii>forbit;set<int>remain;int n, m, k;bool isok(int u, int v){    if(u > v) swap(u, v);    return forbit.find(mp(u, v)) == forbit.end();}void dfs(int u){    vector<int>temp; temp.clear();    for(int i : remain) if(isok(u, i)) temp.pb(i);    for(int i : temp) remain.erase(i);    for(int i : temp) dfs(i);}int main(){    while(scanf("%d%d%d", &n, &m, &k) != EOF) {        forbit.clear(); remain.clear();        int deg = n - 1;        for(int i = 0 ; i < m ; i++) {            int u, v;   scanf("%d%d", &u, &v);            if(u > v) swap(u, v);            forbit.insert(mp(u, v));            if(u == 1) deg--;        }        if(deg < k) {            puts("impossible");            continue;        }        for(int i = 2 ; i <= n ; i++) remain.insert(i);        int cnt = 0;        for(int i = 2 ; i <= n ; i++) {            if(remain.find(i) != remain.end() && isok(1, i)) {                dfs(i);                cnt++;            }        }        if(cnt > k) puts("impossible");        else puts("possible");    }    return 0;}
0 0
原创粉丝点击