UVALive - 6266 Admiral 费用流
题意:找两条完全不相交不重复的路使得权值和最小。
思路:比赛的时候时间都卡在D题了,没有仔细的想这题,其实还是很简单的,将每个点拆开,连一条容量为1,费用为0的边,起点和终点容量为2,两点之间有边就加一条容量为1,费用为权值的边,这样跑一边费用流就可以了。
1 #pragma comment(linker, "/STACK:1000000000") 2 #include <bits/stdc++.h> 3 #define LL long long 4 #define INF 0x3f3f3f3f 5 #define IN freopen("in.txt","r",stdin); 6 #define OUT freopen("out.txt","w",stdout); 7 using namespace std; 8 #define MAXN 9999 9 #define V 2005 10 #define E 30005 11 int vis[V]; 12 int dist[V]; 13 int pre[V]; 14 15 struct Edge{ 16 int u,v,c,cost,next; 17 }edge[E]; 18 int head[V],cnt; 19 20 void init(){ 21 cnt=0; 22 memset(head,-1,sizeof(head)); 23 } 24 void addedge(int u,int v,int c,int cost) 25 { 26 edge[cnt].u=u;edge[cnt].v=v;edge[cnt].cost=cost; 27 edge[cnt].c=c;edge[cnt].next=head[u];head[u]=cnt++; 28 29 edge[cnt].u=v;edge[cnt].v=u;edge[cnt].cost=-cost; 30 edge[cnt].c=0;edge[cnt].next=head[v];head[v]=cnt++; 31 } 32 33 bool spfa(int begin,int end){ 34 int u,v; 35 queue<int> q; 36 for(int i=0;i<=end+2;i++){ 37 pre[i] = -1; 38 vis[i] = 0; 39 dist[i] = INF; 40 } 41 vis[begin]=1; 42 dist[begin]=0; 43 q.push(begin); 44 while(!q.empty()){ 45 u=q.front(); 46 q.pop(); 47 vis[u]=0; 48 for(int i=head[u];i!=-1;i=edge[i].next){ 49 if(edge[i].c>0){ 50 v=edge[i].v; 51 if(dist[v]>dist[u]+edge[i].cost){ 52 dist[v]=dist[u]+edge[i].cost; 53 pre[v]=i; 54 if(!vis[v]){ 55 vis[v]=true; 56 q.push(v); 57 } 58 } 59 } 60 } 61 } 62 return dist[end] != INF; 63 } 64 65 int MCMF(int begin,int end){ 66 int ans=0,flow; 67 int flow_sum=0; 68 while(spfa(begin,end)){ 69 flow=INF; 70 for(int i=pre[end];i!=-1;i=pre[edge[i].u]) 71 if(edge[i].c<flow) 72 flow=edge[i].c; 73 for(int i=pre[end];i!=-1;i=pre[edge[i].u]){ 74 edge[i].c-=flow; 75 edge[i^1].c+=flow; 76 } 77 ans+=dist[end]; 78 flow_sum += flow; 79 } 80 //cout << flow_sum << endl; 81 return ans; 82 } 83 84 int main() 85 { 86 //IN; 87 int n, m, x, y, z; 88 while(~scanf("%d%d", &n, &m)){ 89 init(); 90 int s = 1, t = 2 * n; 91 for(int i = 2; i < n; i++){ 92 addedge(i, i + n, 1, 0); 93 } 94 addedge(1, n + 1, 2, 0); 95 addedge(n, n << 1, 2, 0); 96 for(int i = 1; i <= m; i++){ 97 scanf("%d%d%d", &x, &y, &z); 98 addedge(x + n, y, 1, z); 99 } 100 int ans = MCMF(s, t); 101 printf("%d\n", ans); 102 } 103 return 0; 104 }