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;
数据保证图中没有自环。

Output

 输出一行一个整数表示最少需要删掉的边的数量。

Sample Input

3 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 }

 

 
 
posted @ 2019-05-03 20:13  Frontierone  阅读(115)  评论(0编辑  收藏  举报