题意:有n个景点,每个景点之间有一些带权有向边,要求你设计一些线路,要求线路是一个圈,并且每个景点只能有一条线路经过,并且只能经过一次(起始点除外),问你,若存在,求这些线路权值的最小和,否则输出"N"
分析:这题和上一题HDU差不多,只是这题有可能不存在解决方案.同样这题也有重边
若不存在解决方案,则对于有些点,不存在Left[i]和i的边,故w[Left[i]][i]=-INF;
http://www.cnblogs.com/arbitrary/archive/2013/04/21/3034424.html
// File Name: 1349.cpp // Author: Zlbing // Created Time: 2013/4/21 20:48:33 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) const int MAXN=105; int Left[MAXN]; int w[MAXN][MAXN]; int Lx[MAXN],Ly[MAXN]; bool S[MAXN],T[MAXN]; int N; bool match(int i) { S[i]=true; for(int j=1;j<=N;j++)if(Lx[i]+Ly[j]==w[i][j]&&!T[j]) { T[j]=true; if(Left[j]==0||match(Left[j])) { Left[j]=i; return true; } } return false; } void update(){ int a=INF; for(int i=1;i<=N;i++)if(S[i]) for(int j=1;j<=N;j++)if(!T[j]) a=min(a,Lx[i]+Ly[j]-w[i][j]); for(int i=1;i<=N;i++){ if(S[i])Lx[i]-=a; if(T[i])Ly[i]+=a; } } void KM() { for(int i=1;i<=N;i++){ Left[i]=Lx[i]=Ly[i]=0; for(int j=1;j<=N;j++) { Lx[i]=max(Lx[i],w[i][j]); } } for(int i=1;i<=N;i++){ for(;;){ CL(S,0); CL(T,0); if(match(i))break; else update(); } } } int main() { while(~scanf("%d",&N)) { if(!N)break; REP(i,0,N) REP(j,0,N) w[i][j]=-INF; REP(i,1,N) { while(true){ int a,b; scanf("%d",&a); if(!a)break; scanf("%d",&b); w[i][a]=max(w[i][a],-b); } } KM(); bool flag=true; REP(i,1,N)if(w[Left[i]][i]==-INF)flag=false; // REP(i,1,N) // { // REP(j,1,N) // printf("w[%d][%d]=%d ",i,j,w[i][j]); // printf("\n"); // } // REP(i,1,N)printf("Left%d\n",Left[i]); int ans=0; if(flag) { REP(i,1,N) ans+=-w[Left[i]][i]; printf("%d\n",ans); } else printf("N\n"); } return 0; }