[ZJOI2011] minimum cut

Title Description
White in graph theory lesson learned a new concept - the smallest cut, after school White wrote these words in a notebook as follows: "For a map, a division of graph nodes will map All the nodes into two parts, if the node s, t are not in the same section, called the division is about s, t of the cutting.

For a weighted graph, the values ​​of all vertices in the capacity defined as the cut edge weights of different portions obtained by adding, the minimum s, t of the cutting means is cutting about s, t in the capacity of the smallest cut "

Now given an undirected graph, there are several white shaped like "figure on how many points they are of minimal cut capacity not exceeding x it," the question, although small blue wanted to answer these questions, but recently a small blue busy digging pieces of wood, so as still the little blue friend, you have a mission.

Input format
input file and only the first line of a positive integer T, represents a group of test data. For each test, the first line contains two integers n, m, represents the points and edges of FIG. The following m lines of three positive integers u, v, c (1 < = u, v <= n, 0 <= c <= 106), expressed a weight of c undirected edge (u, v) the next line contains an integer q, q represents inquiry number of following lines, each integer x, which is entitled the same meaning as described.

Output Format
For each test case, the output line should include q i-th row i represents the answer to the first question. For point (p, q) and (q, p), counted only once (see sample). Separated by a blank line between the two sets of test data.

Sample Input Output
Input # 1 Copy
1
. 5 0
1
0
output copy # 1
10
Description / Tips
[Data] range

To 100% of the data T <= 10, n <= 150, m <= 3000, q <= 30, the 32-bit signed integer type range in x.

There may be multiple edges between two points in FIG.


First seek what minimum cut tree, the distance between any two points added to the vector which, finally upper_bound find what you can.

But be careful, if you can not reach, should return 0 instead of INF.

There are output blank lines


AC Code:

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=210,M=1e5+10;
int n,m,q,T;
struct maxflow{
    int head[N],nex[M],to[M],w[M],h[N],tot=1,s,t;   queue<int> q;  
    inline void ade(int a,int b,int c){
        to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;
    }
    inline void add(int a,int b,int c){ade(a,b,c);  ade(b,a,0);}
    inline int bfs(){
        q.push(s);  memset(h,0,sizeof h);   h[s]=1;
        while(q.size()){
            int u=q.front();    q.pop();
            for(int i=head[u];i;i=nex[i]){
                if(w[i]&&!h[to[i]]){
                    h[to[i]]=h[u]+1;    q.push(to[i]);
                }
            }
        }
        return h[t];
    }
    int dfs(int x,int f){
        if(x==t)    return f;   int fl=0;
        for(int i=head[x];i&&f;i=nex[i]){
            if(w[i]&&h[to[i]]==h[x]+1){
                int mi=dfs(to[i],min(w[i],f));
                w[i]-=mi,w[i^1]+=mi,fl+=mi,f-=mi;
            }
        }
        if(!fl) h[x]=-1;
        return fl;
    }
    inline void init(){
    	for(int i=2;i<=tot;i+=2)	w[i]+=w[i^1],w[i^1]=0;
	}
    inline int dinic(){
        int res=0;  init();
        while(bfs())    res+=dfs(s,inf);
        return res;
    }
}d;
struct min_cut_tree{
    int head[N],nex[M],to[M],w[M],tot=0;
    inline void ade(int a,int b,int c){
        to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;
    }
    inline void add(int a,int b,int c){ade(a,b,c);  ade(b,a,0);}
    int a[N],b[N],c[N];
    void build(int l,int r){
        if(l==r)    return ;
        d.s=a[l],d.t=a[l+1];    int flow=d.dinic();
        add(a[l],a[l+1],flow);
        int cnt1=0,cnt2=0;
        for(int i=l;i<=r;i++){
            if(d.h[a[i]])   b[++cnt1]=a[i];
            else    c[++cnt2]=a[i];
        }
        for(int i=l;i<=l+cnt1-1;i++)    a[i]=b[i-l+1];
        for(int i=l+cnt1;i<=r;i++)  a[i]=c[i-cnt1-l+1];
        build(l,l+cnt1-1);  build(l+cnt1,r);
    }
    int h[N],f[N][10],mi[N][10],lg[N];
    void dfs(int x,int fa){
        h[x]=h[fa]+1;
        for(int i=1;(1<<i)<=h[x];i++){
            f[x][i]=f[f[x][i-1]][i-1];
            mi[x][i]=min(mi[x][i-1],mi[f[x][i-1]][i-1]);
        }
        for(int i=head[x];i;i=nex[i]){
            if(to[i]==fa)   continue;
            f[to[i]][0]=x; mi[to[i]][0]=w[i];
            dfs(to[i],x);
        }
    }
    void solve(){
        for(int i=1;i<=n;i++)   lg[i]=lg[i-1]+(1<<lg[i-1]==i);
        memset(head,0,sizeof head);	tot=0;
        for(int i=1;i<=n;i++)   a[i]=i;
        build(1,n); dfs(1,0);
    }
    inline int ask(int x,int y){
        int res=inf;
        if(h[x]<h[y])   swap(x,y);
        while(h[x]>h[y]){
            res=min(res,mi[x][lg[h[x]-h[y]]-1]);
            x=f[x][lg[h[x]-h[y]]-1];
        }
        if(x==y)    return res;
        for(int i=lg[h[x]]-1;i>=0;i--){
            if(f[x][i]!=f[y][i]){
                res=min(res,mi[x][i]); res=min(res,mi[y][i]);
                x=f[x][i],y=f[y][i];
            }
        }
        res=min(res,mi[x][0]); res=min(res,mi[y][0]);
        if(res==inf)	return 0;
        return res;
    }
}mct;
int main(){
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    cin>>T;
    while(T--){
    	cin>>n>>m; d.tot=1; memset(d.head,0,sizeof d.head);
    	for(int i=1,a,b,c;i<=m;i++)	cin>>a>>b>>c,d.add(a,b,c),d.add(b,a,c);
    	vector<int> v; mct.solve();
    	for(int i=1;i<=n;i++)	
			for(int j=i+1;j<=n;j++)	v.push_back(mct.ask(i,j));
		sort(v.begin(),v.end());
		cin>>q;
		while(q--){
			int x;	cin>>x; 
			cout<<upper_bound(v.begin(),v.end(),x)-v.begin()<<'\n';
		}
		cout<<'\n';
	}
    return 0;
}
Published 416 original articles · won praise 228 · views 10000 +

Guess you like

Origin blog.csdn.net/weixin_43826249/article/details/103717076