BZOJ2561 最小生成树
Description
给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?
Input
第一行包含用空格隔开的两个整数,分别为N和M;
接下来M行,每行包含三个正整数u,v和w表示图G存在一条边权为w的边(u,v)。
最后一行包含用空格隔开的三个整数,分别为u,v,和 L;
数据保证图中没有自环。
接下来M行,每行包含三个正整数u,v和w表示图G存在一条边权为w的边(u,v)。
最后一行包含用空格隔开的三个整数,分别为u,v,和 L;
数据保证图中没有自环。
Output
输出一行一个整数表示最少需要删掉的边的数量。
Sample Input
3 2
3 2 1
1 2 3
1 2 2
3 2 1
1 2 3
1 2 2
Sample Output
1
HINT
对于20%的数据满足N ≤ 10,M ≤ 20,L ≤ 20;
对于50%的数据满足N ≤ 300,M ≤ 3000,L ≤ 200;
对于100%的数据满足N ≤ 20000,M ≤ 200000,L ≤ 20000。
还是不看题解不会系列。看了题解还忽略细节系列。
首先和最小生成树联系,一条边(u,v)能够作为MST中的一条边,条件是权值比它小的边,不能够联通u和v,所以思路来了,用权值比它小的建图,流量为1,然后求最小割即可。最大生成树同理。通过这道题让我意识到了我不熟悉我用的模板的哪个部分。
但是我直接建的单向边,我发现题解都是双向边,不是太理解。然后画个这个图,就明白了。
如果建单向边,2和3的那条边,不一定会被割掉。(易知)
然后就发现我的模板里面addedge操作,直接就建了两条边,按照题目的数据量。20w*2*2=80w, 我开的40w不够用。
还有一个地方是,我的模板,需要知道图中共有多少个点,然后只能无脑set了一波,然后又发现,建图的时候可能不会出现u,v。然后就用标记了一下,才得到总点数,比较麻烦。
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=100010; 5 const int maxm=1000010; 6 const int inf=0x3f3f3f3f; 7 struct Edge{ 8 int to,next,cap,flow,cost; 9 }edge[maxm]; 10 11 int tol; 12 int head[maxn]; 13 int gap[maxn],dep[maxn],cur[maxn]; 14 void init() { 15 tol=0; 16 memset(head,-1,sizeof(head)); 17 } 18 void addedge(int u,int v,int w,int rw=0) { 19 edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0; 20 edge[tol].next=head[u];head[u]=tol++; 21 edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0; 22 edge[tol].next=head[v];head[v]=tol++; 23 } 24 25 int Q[maxn]; 26 void bfs(int start,int end) { 27 memset(dep,-1,sizeof(dep)); 28 memset(gap,0,sizeof(gap)); 29 gap[0]=1; 30 int front=0,rear=0; 31 dep[end]=0; 32 Q[rear++]=end; 33 while(front!=rear) { 34 int u=Q[front++]; 35 for(int i=head[u];i!=-1;i=edge[i].next) { 36 int v=edge[i].to; 37 if(dep[v]!=-1) continue; 38 Q[rear++]=v; 39 dep[v]=dep[u]+1; 40 gap[dep[v]]++; 41 } 42 } 43 } 44 45 int S[maxn]; 46 int sap(int start,int end,int n) { 47 bfs(start,end); 48 memcpy(cur,head,sizeof(head)); 49 int top=0; 50 int u=start; 51 int ans=0; 52 while(dep[start]<n) { 53 if(u==end) { 54 int minn=inf; 55 int inser; 56 for(int i=0;i<top;i++) { 57 if(minn>edge[S[i]].cap-edge[S[i]].flow) { 58 minn=edge[S[i]].cap-edge[S[i]].flow; 59 inser=i; 60 } 61 } 62 for(int i=0;i<top;i++) { 63 edge[S[i]].flow+=minn; 64 edge[S[i]^1].flow-=minn; 65 } 66 ans+=minn; 67 top=inser; 68 u=edge[S[top]^1].to; 69 continue; 70 } 71 bool flag=false; 72 int v; 73 for(int i=cur[u];i!=-1;i=edge[i].next) { 74 v=edge[i].to; 75 if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]) { 76 flag=true; 77 cur[u]=i; 78 break; 79 } 80 } 81 if(flag) { 82 S[top++]=cur[u]; 83 u=v; 84 continue; 85 } 86 int minn=n; 87 for(int i=head[u];i!=-1;i=edge[i].next) { 88 if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<minn) { 89 minn=dep[edge[i].to]; 90 cur[u]=i; 91 } 92 } 93 gap[dep[u]]--; 94 if(!gap[dep[u]]) return ans; 95 dep[u]=minn+1; 96 gap[dep[u]]++; 97 if(u!=start) u=edge[S[--top]^1].to; 98 } 99 return ans; 100 } 101 102 struct node{ 103 int u,v,w; 104 bool operator <(const node &b)const { 105 return w<b.w; 106 } 107 }edge_2[maxm]; 108 109 int main() { 110 int n,m; 111 while(~scanf("%d%d",&n,&m)) { 112 for(int i=1;i<=m;i++) { 113 scanf("%d%d%d",&edge_2[i].u,&edge_2[i].v,&edge_2[i].w); 114 } 115 sort(edge_2+1,edge_2+m+1); 116 int u,v,l,ans=0,tmp; 117 scanf("%d%d%d",&u,&v,&l); 118 init(); 119 set<int> sit; 120 bool flagu=false,flagv=false; 121 for(int i=1;i<=m;i++) { 122 if(edge_2[i].w<l) { 123 if(edge_2[i].u==u||edge_2[i].v==u) flagu=true; 124 if(edge_2[i].u==v||edge_2[i].v==v) flagv=true; 125 addedge(edge_2[i].u,edge_2[i].v,1); 126 addedge(edge_2[i].v,edge_2[i].u,1); 127 sit.insert(edge_2[i].u); 128 sit.insert(edge_2[i].v); 129 } else break; 130 } 131 tmp=2-flagu-flagv; 132 ans+=sap(u,v,sit.size()+tmp); 133 init(); 134 sit.clear(); 135 flagu=false,flagv=false; 136 for(int i=m;i>=1;i--) { 137 if(edge_2[i].w>l) { 138 if(edge_2[i].u==u||edge_2[i].v==u) flagu=true; 139 if(edge_2[i].u==v||edge_2[i].v==v) flagv=true; 140 addedge(edge_2[i].u,edge_2[i].v,1); 141 addedge(edge_2[i].v,edge_2[i].u,1); 142 sit.insert(edge_2[i].u); 143 sit.insert(edge_2[i].v); 144 } else break; 145 } 146 tmp=2-flagu-flagv; 147 ans+=sap(u,v,sit.size()); 148 printf("%d\n",ans); 149 } 150 }
埋骨何须桑梓地,人生无处不青山