BZOJ4435——[Cerc2015]Juice Junctions

来源:互联网 发布:vb计算圆的面积和周长 编辑:程序博客网 时间:2024/05/20 08:21

0、题目大意:求两点之间的最小割之和

1、分析:很明显,最小割树,我们发现这个题并不能用n^3的方法来求答案。。

   所以我们记录下所有的边,然后把边从大到小排序,然后跑一边类似kruskal的东西,顺便统计答案

   TAT,这个题我被卡常数了,贴上TLE的代码吧。。。

#include <queue>#include <ctime>#include <cstdio>#include <cstring>#include <cstring>#include <algorithm>using namespace std;#define LL long long#define inf 214748364 struct Edge{    int from, to, cap, flow, next;};int head[3010], cur[3010];Edge G[20010];int tot;int d[3010];bool vis[3010];int s, t, n, m;int a[3010];int b[3010]; inline void init(){    memset(head, -1, sizeof(head));    tot = -1;    return;} inline void insert(int from, int to, int cap){    G[++ tot] = (Edge){from, to, cap, 0, head[from]};    head[from] = tot;    G[++ tot] = (Edge){to, from, 0, 0, head[to]};    head[to] = tot;    return;} inline bool BFS(){    for(int i = 1; i <= n; i ++) vis[i] = 0;    queue<int> Q;    Q.push(s);    vis[s]=1;    d[s]=0;    while(!Q.empty()){        int x = Q.front(); Q.pop();        for(int i = head[x]; i != -1; i = G[i].next){            Edge& e = G[i];            if(e.cap - e.flow > 0 && !vis[e.to]){                vis[e.to] = 1;                d[e.to]=d[x]+1;                Q.push(e.to);            }        }    }    return vis[t];} inline int dfs(int x, int a){    if(x == t || a == 0) return a;    int flow = 0, f;    for(int& i = cur[x]; i != -1; i = G[i].next){        Edge& e = G[i];        if(d[x]+1 == d[e.to] && (f = dfs(e.to, min(e.cap - e.flow, a))) > 0){            e.flow += f;            G[i ^ 1].flow -= f;            flow += f;            a -= f;            if(a == 0) break;        }    }    return flow;} inline int maxflow(){    int res = 0;    while(BFS()){        for(int i = 1; i <= n; i ++) cur[i] = head[i];        res += dfs(s, inf);    }    return res;}  inline void Clear(){    for(int i = 0; i <= tot; i += 2){        G[i].flow = G[i ^ 1].flow = (G[i].flow + G[i ^ 1].flow) / 2;    }} struct node{    int u, v, w;    inline bool operator < (const node& rhs) const{        return w > rhs.w;    }} T[20010];int num; inline void add(int u, int v, int w){    T[++ num].u = u;    T[num].v = v;    T[num].w = w;} inline void solve(int l, int r){    if(l == r) return;    int rl = rand() % (r - l + 1) + l;    int rr = rand() % (r - l + 1) + l;    if(rl == rr) rl ++;    if(rl > r) rl -= 2;    s = a[rl], t = a[rr];    Clear();     int tw = maxflow();    //puts("fuck");    add(a[rl], a[rr], tw);    int L = l, R = r;    for(int i = l; i <= r; i ++){        if(vis[a[i]]) b[L ++] = a[i];        else b[R --] = a[i];    }    for(int i = l; i <= r; i ++) a[i] = b[i];    solve(l, L - 1); solve(L, r);} int ff[20010], size[20010]; inline int find(int x){    return ff[x] == x ? x : ff[x] = find(ff[x]);} int main(){   // srand(time(NULL));    scanf("%d%d", &n, &m);    init();    for(int i = 1; i <= m; i ++){        int u, v;        scanf("%d%d", &u, &v);        insert(u, v, 1); insert(v, u, 1);    }    for(int i = 1; i <= n; i ++) a[i] = i;    solve(1, n);    LL ret = 0;    sort(T + 1, T + num + 1);    for(int i = 1; i <= n; i ++) size[i] = 1, ff[i] = i;   // puts("fuck");    for(int i = 1; i <= num; i ++){        int tx = find(T[i].u), ty = find(T[i].v);        if(size[tx] < size[ty]) swap(tx, ty);        ret += (LL)T[i].w * size[tx] * size[ty];        ff[ty] = tx;        size[tx] += size[ty];    }    printf("%lld\n", ret);    return 0;}


0 0
原创粉丝点击