zoj 2676 Network Wars(01分數規劃+網路流)
阿新 • • 發佈:2019-01-29
求一個割集 使得割集的平均邊權最小
具體的解答 請看Amber論文《最小割模型在資訊學競賽中的應用》
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <string.h> #include <string> #include <vector> #include <queue> #define MEM(a,x) memset(a,x,sizeof a) #define eps 1e-8 #define MOD 10009 #define MAXN 100010 #define MAXM 50100 #define INF 99999999 #define ll __int64 #define bug cout<<"here"<<endl #define fread freopen("ceshi.txt","r",stdin) #define fwrite freopen("out.txt","w",stdout) using namespace std; struct Edge { int to,next; double flow,cap; }edge[MAXM]; int tol; int head[MAXN]; int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN]; void init() { tol=0; MEM(head,-1); } void addedge(int u,int v,double w,double rw) { edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u]; edge[tol].flow=0; head[u]=tol++; edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v]; edge[tol].flow=0; head[v]=tol++; } double sap(int start,int ed,int N) { MEM(gap,0); MEM(dep,0); memcpy(cur,head,sizeof(head)); // for(int i=start;i<=ed;i++) // cur[i]=head[i]; int u=start; pre[u]=-1; gap[0]=N; double ans=0; while(dep[start]<N) { if(u==ed) { double Min=INF*1.0; for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]) if(Min>edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow; for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; } u=start; ans+=Min; continue; } bool flag=0; int v; for(int i=cur[u];i!=-1;i=edge[i].next) { v=edge[i].to; if((edge[i].cap-edge[i].flow)>eps&&dep[v]+1==dep[u]) { flag=1; cur[u]=pre[v]=i; break; } } if(flag) { u=v; continue; } int Min=N; for(int i=head[u];i!=-1;i=edge[i].next) if((edge[i].cap-edge[i].flow)>eps&&dep[edge[i].to]<Min) { Min=dep[edge[i].to]; cur[u]=i; } gap[dep[u]]--; if(!gap[dep[u]]) return ans; dep[u]=Min+1; gap[dep[u]]++; if(u!=start) u=edge[pre[u]^1].to; } return ans; } struct point { int u,v; double w; }po[MAXM]; int vis[MAXN]; void dfs(int u) { vis[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) if(edge[i].cap-edge[i].flow>eps&&!vis[edge[i].to]) dfs(edge[i].to); } int main() { // fread; int n,m; int cs=0; while(scanf("%d%d",&n,&m)!=EOF) { double st=10000010,ed=0.0; for(int i=0;i<m;i++) { scanf("%d%d%lf",&po[i].u,&po[i].v,&po[i].w); st=min(st,po[i].w); ed=max(ed,po[i].w); } // double st=0.0,ed=10000010; double mid; double flow; while(ed-st>eps) { init(); mid=(ed+st)/2.0; flow=0; for(int i=0;i<m;i++) { if(po[i].w<=mid) flow+=po[i].w-mid; else addedge(po[i].u,po[i].v,po[i].w-mid,po[i].w-mid); } flow+=sap(1,n,n); if(flow>0) st=mid; else ed=mid; } init(); for(int i=0;i<m;i++) { if(po[i].w<=ed) continue; addedge(po[i].u,po[i].v,po[i].w-ed,po[i].w-ed); } sap(1,n,n); MEM(vis,0); dfs(1); vector<int> ans; for(int i=0;i<m;i++) { if((po[i].w<=ed)||(vis[po[i].u]&&!vis[po[i].v])||(!vis[po[i].u]&&vis[po[i].v])) ans.push_back(i+1); } int num=ans.size(); if(cs) puts(""); else cs=1; printf("%d\n",num); for(int i=0;i<num;i++) { if(i) printf(" "); printf("%d",ans[i]); } printf("\n"); ans.clear(); } return 0; }