【拆点费用流】【HDU1853】【 Cyclic Tour】
题意:
XD 第一次知道网络流拆点做法 但还没完全理解透,多做几题感悟感悟 ,先发一下别人题解 ,代码当然自己写
思路:
对于满足条件的环,每个点的入度和出度均为1,我们可以把每个点拆成入点和出点,那么也就是说一个入点对应一个出点,一个出点对应一个入点。那么这个问题就变成了一个最佳匹配问题。
代码:
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #include <queue> #define oo 0x13131313 using namespace std; const int MAXN=300; const int MAXM=300000; const int INF=0x3f3f3f3f; struct Edge { int to,next,cap,flow,cost; void get(int a,int b,int c,int d) { to=a,cap=b,cost=c;next=d;flow=0; } }edge[MAXM]; int head[MAXN],tol; int pre[MAXN],dis[MAXN]; bool vis[MAXN]; int N; void init(int n) { N=n; tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int cap,int cost) { edge[tol].get(v,cap,cost,head[u]);head[u]=tol++; edge[tol].get(u,0,-cost,head[v]);head[v]=tol++; } bool spfa(int s,int t) { queue<int>q; for(int i=0;i<N;i++) { dis[i]=INF; vis[i]=false; pre[i]=-1; } dis[s]=0; vis[s]=true; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i= head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].cap>edge[i].flow&& dis[v]>dis[u]+edge[i].cost ) { dis[v]=dis[u]+edge[i].cost; pre[v]=i; if(!vis[v]) { vis[v]=true; q.push(v); } } } } if(pre[t]==-1) return false; else return true; } int minCostMaxflow(int s,int t,int &cost) { int flow=0; cost = 0; while(spfa(s,t)) { int Min=INF; for(int i=pre[t];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[t];i!=-1;i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; cost+=edge[i].cost*Min; } flow+=Min; } return flow; } int NN,MM; void input() { int a,b,c; for(int i=1;i<=MM;i++) { scanf("%d%d%d",&a,&b,&c); addedge(a,b+NN,1,c); } } void solve() { int s=NN*2+1,t=NN*2+2,k,ANS; for(int i=1;i<=NN;i++) { addedge(s,i,1,0); addedge(i+NN,t,1,0); } k=minCostMaxflow(s,t,ANS); if(k==NN) printf("%d\n",ANS); else printf("-1\n"); } void File() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } int main() { // File(); while(cin>>NN>>MM) { init(MAXN); input(); solve(); } return 0; }