您的位置:首页 > 其它

hdu 3435 A new Graph Game

2011-07-03 16:17 405 查看
//邻接表 2859MS
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1010*2;
const int maxm=10010*10;//最大顶点数和边数
const int maxl=999999999;
inline int Min(int a,int b)
{
return a<b?a:b;
}
inline int Max(int a,int b)
{
return a>b?a:b;
}
struct st
{
int y,d;
int ne;
int bro;
int f;
} e[maxm];
int ee;
int st[maxn];
int n,m;
int F;
void addedge(int x,int y,int d,int f)
{
//给顶点x和y间添加一条费用d,流量f的边
e[ee].y=y;
e[ee].d=d;
e[ee].ne=st[x];
e[ee].f=f;
st[x]=ee++;
e[ee].y=x;
e[ee].d=-1*d;
e[ee].ne=st[y];
e[ee].f=0;
st[y]=ee++;
e[ee-2].bro=ee-1;
e[ee-1].bro=ee-2;
}
int d[maxn],p[maxn];
//spfa所用到起点的最短距离(这里距离相当于cost)和路径记录之前的一个节点
int c[maxn];//spfa所用数组:是否在队列中
int que[maxn],head,tail;//spfa专用队列
int spfa(int sx,int ex)//求sx到ex的一次费用增广
{
//如果没有增广路就返回maxl 否则返回费用
int i,j,k;
for (i=0; i<maxn; i++) d[i]=maxl;
memset(c,0,sizeof(c));//初始化都没进
d[sx]=0;
que[head=0]=sx;
tail=1;
c[sx]=1;
while (head!=tail)
{
k=que[head++];
head%=maxn;
c[k]=0;
for (i=st[k]; i!=-1; i=e[i].ne) if (e[i].f)
if (d[k]+e[i].d<d[e[i].y])
{
d[e[i].y]=d[k]+e[i].d;
p[e[i].y]=i;
if (c[e[i].y]==0)
{
c[e[i].y]=1;
if (e[i].d<0)
{
head=(head-1+maxn)%maxn;
que[head]=e[i].y;
}
else
{
que[tail++]=e[i].y;
tail%=maxn;
}
}
}
}
if (d[ex]==maxl) return maxl;
//如果无法到达终点返回maxl
k=maxl;
for (i=ex; i!=sx; i=e[e[p[i]].bro].y)
k=Min(k,e[p[i]].f); //计算流
//sum+=k; //sum计算流量
F+=k;
for (i=ex; i!=sx; i=e[e[p[i]].bro].y) //增加反向边
{
e[p[i]].f-=k;
e[e[p[i]].bro].f+=k;
}
return d[ex]*k;
//返回费用为流大小*路径长度(cost累加)
}
int main()
{
int T;
int cas=1;
int m;
scanf("%d",&T);
while(T--)
{
int nn,mm;
scanf("%d%d",&nn,&mm);
memset(st,-1,sizeof(st));
ee=0;

for(int i=1; i<=mm; i++)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
addedge(x,y+nn,c,1);
addedge(y,x+nn,c,1);
}

for(int i=1; i<=nn; i++)
{
addedge(0,i,0,1);
addedge(i+nn,nn+nn+1,0,1);
}

n=nn*2+2;
F=0;
int tot=0,k;
while ((k=spfa(0,n-1))!=maxl) tot+=k;

//printf("%")
if(F!=nn)  printf("Case %d: NO\n",cas++);
else printf("Case %d: %d\n",cas++,tot);
}
return 0;
}


//c++ 2390ms
//完美匹配
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=1<<28;
int g[1005][1005],lx[1005],ly[1005];//顶点标号
bool sx[1005],sy[1005];//是否已经搜索过
int link[1005],n,stack[1005];
bool path(int k)
{
sx[k]=true;
for(int i=1; i<=n; i++)
{
if(sy[i]) continue;
int t=ly[i]+lx[k]-g[k][i];
if(t==0)
{
sy[i]=1;
if(link[i]==-1||path(link[i]))
{
link[i]=k;
return true;
}
}
else if(stack[i]>t) stack[i]=t;
}
return false;
}
int BestMatch()
{
int d,sum;
memset(ly,0,sizeof(ly));
memset(link,-1,sizeof(link));
for(int i=1; i<=n; i++)
{
lx[i]=-inf;
for(int j=1; j<=n; j++)
if(lx[i]<g[i][j]&&g[i][j]!=0) lx[i]=g[i][j];
}
for(int k=1; k<=n; k++)
{
for (int i=1; i<=n; i++) stack[i]=inf;
while(1)
{
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
if(path(k)) break;
d=inf;
for(int i=1; i<=n; i++)
if (!sy[i]&&stack[i]<d) d=stack[i];
for(int i=1; i<=n; i++)
if(sx[i]) lx[i]-=d;
for(int i=1; i<=n; i++)
if(sy[i]) ly[i]+=d;
else stack[i]-=d;
}
}
sum=0;
for(int i=1; i<=n; i++)
{
if(link[i]==-1||g[link[i]][i]==-inf) return -1;
sum+=g[link[i]][i];
}
return -sum;
}
int main()
{
int T;
int cas=1;
int m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
g[i][j]=inf;
for(int i=1; i<=m; i++)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
g[x][y]=g[y][x]=min(g[x][y],c);
}
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) g[i][j]=-g[i][j];

int t=BestMatch();
if(t==-1) printf("Case %d: NO\n",cas++);
else printf("Case %d: %d\n",cas++,t);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  graph path c struct