最小生成树
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2561
题解:
这题竟然是网络流。。。
考虑kruskal,先把比x小的边加入,只有在此之前u,v不连通那么才有用,所以其实就是最小割
大的边同理
两次答案相加就是结果(因为两次删的边不会重复)
网络流也算是改变认知了,,知道思路只剩建图模板
#include <bits/stdc++.h> using namespace std; #define maxn 500000 #define INF 1e9 struct ree{ int a,b,c,flow; }a[maxn]; struct re{ int a,b,c; }c[maxn],b[maxn]; bool vis[maxn/2]; int l,n,m,a1,b1,l1,s,t,head[maxn],d[maxn]; bool cmp1(re a,re b) { return(a.c<b.c); } bool cmp2(re a,re b) { return(a.c>b.c); } void arr(int x,int y,int z,int flow) { a[++l].a=head[x]; a[l].b=y; a[l].c=z; a[l].flow=flow; head[x]=l; } bool bfs(){ memset(vis,0,sizeof(vis)); queue<int> q; q.push(s); d[s]=0; vis[s]=1; while (!q.empty()) { int x=q.front();q.pop(); int u=head[x]; while (u) { int v=a[u].b; if (!vis[v]&&a[u].c>a[u].flow) { vis[v]=1; d[v]=d[x]+1; q.push(v); } u=a[u].a; } } return(vis[t]); } int dfs(int x,int y) { if (x==t||y==0) return y; int flow=0,f,tmp; int u=head[x]; while (u) { int v=a[u].b; if (d[x]+1==d[v]&&(f=dfs(v,min(y,a[u].c-a[u].flow)))>0) { a[u].flow+=f; if (u%2) tmp=u+1; else tmp=u-1; a[tmp].flow-=f; flow+=f; y-=f; if (y==0) break; } u=a[u].a; } return(flow); } int maxflow() { int flow=0; while (bfs()) { flow+=dfs(s,INF); } return(flow); } int main() { cin>>n>>m; for (int i=1;i<=m;i++) cin>>c[i].a>>c[i].b>>c[i].c; memcpy(b,c,sizeof(c)); sort(c+1,c+m+1,cmp1); sort(b+1,b+m+1,cmp2); cin>>a1>>b1>>l1; s=a1;t=b1; for (int i=1;i<=m;i++) if (c[i].c>=l1) break; else { arr(c[i].a,c[i].b,1,0); arr(c[i].b,c[i].a,1,0); } int ans=maxflow(); memset(head,0,sizeof(head)); l=0; for(int i=1;i<=m;i++) if (b[i].c<=l1) break; else{ arr(b[i].a,b[i].b,1,0); arr(b[i].b,b[i].a,1,0); } ans+=maxflow(); cout<<ans<<endl; return 0; }