您的位置:首页 > 其它

HDU 2121 Ice_cream’s world II(不定根最小树形图)

2015-02-19 12:45 253 查看
大概题意是找出一个点,以这个点为根的最小树形图权值和最小,输出最小树形图的权值以及点的编号。

不定根,所以我们要添加一个虚根...然后就是很多大牛说的方法了...

不过我一直很纳闷,我枚举每一个点为根求最小树形图..然后找出最小,这个一直WA,不明白为啥不是TLE,难道是模板问题?但是我的虚根是1或者n+1都是没问题,看起来不像是只能处理固定点的..求路过的大神解释一下..

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<iostream>
using namespace std;
#define inf 0x3fffffff
struct node
{
int u,v,w;
} edge[30000];
int pre[1020],in[1020],id[1020],use[1020],pos;
int mini_tree(int root,int n,int m)//分别是树根,节点数,边数,序号从1开始
{
int ans=0;
int i,u;
while(1)
{
for(i=1; i<=n; i++)
in[i]=inf;
for(i=1; i<=m; i++)
{
int u=edge[i].u;
int v=edge[i].v;
if(edge[i].w<in[v]&&u!=v)
{
in[v]=edge[i].w;
pre[v]=u;
if(u==root)
pos=i;
}
}//找最小的入边
for(i=1; i<=n; i++)
{
if(i==root)continue;
ans+=in[i];//把边权加起来
if(in[i]==inf)//如果存在没有入弧的点则不存在最小树形图
return -1;
}
memset(id,-1,sizeof(id));
memset(use,-1,sizeof(use));
int cnt=0;
for(i=1; i<=n; i++) //枚举每个点,搜索找环
{
int v=i;
while(v!=root&&use[v]!=i&&id[v]==-1)
{
use[v]=i;
v=pre[v];
}
if(v!=root&&id[v]==-1)//当找到环的时候缩点编号
{
++cnt;
id[v]=cnt;
for(u=pre[v]; u!=v; u=pre[u])
id[u]=cnt;
}
}
if(cnt==0)//如果没有环结束程序
break;
for(i=1; i<=n; i++) //把余下的不在环里的点编号
if(id[i]==-1)
id[i]=++cnt;
for(i=1; i<=m; i++) //建立新的图
{
int u=edge[i].u;
int v=edge[i].v;
edge[i].u=id[u];
edge[i].v=id[v];
if(edge[i].u!=edge[i].v)
edge[i].w-=in[v];
}
n=cnt;//更新节点数和根节点的编号
root=id[root];
}
return ans;
}
int main()
{
int n,m,u,v,w,sum;
while(scanf("%d%d",&n,&m)!=EOF)
{
sum=0;
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&u,&v,&w);
edge[i].u=u+1;
edge[i].v=v+1;
edge[i].w=w;
sum+=w;
}
sum++;
for(int i=1; i<=n; i++)
{
edge[m+i].u=n+1;
edge[m+i].v=i;
edge[m+i].w=sum;
}
int ans=mini_tree(n+1,n+1,n+m);
if(ans==-1||ans-sum>=sum)
printf("impossible\n");
else
printf("%d %d\n",ans-sum,pos-m-1);
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: