hdu 2121无根最小树形图要建一个虚拟节点

#include<stdio.h>
#include<string.h>
#define inf 999999999
#define N  1100
struct node {
int u,v,w;
}edge[11000];
int visit[N],dis[N],id[N],pre[N],yong,n,index;
void addedge(int u,int v,int w){
edge[yong].u=u;
edge[yong].v=v;
edge[yong++].w=w;
}
int  zhuliu(int root) {//朱刘算法模板
 int sum=0;
 n++;
 while(1) {
        int i;
    for(i=0;i<n;i++)
        dis[i]=inf;
        memset(id,-1,sizeof(id));
        memset(visit,-1,sizeof(visit));
        for(i=0;i<yong;i++) {
            int u=edge[i].u,v=edge[i].v;
            if(dis[v]>edge[i].w&&u!=v){
                pre[v]=u;
                dis[v]=edge[i].w;
                if(u==root)//记录最后与根节点连接的边
                    index=i;
            }
        }
        pre[root]=root;
        dis[root]=0;
        for(i=0;i<n;i++) {
                if(i==root)continue;
            if(dis[i]==inf)return -1;
            sum+=dis[i];
        }
        int res=0;
        for(i=0;i<n;i++)
            if(visit[i]==-1) {
            int v=i;
            while(visit[v]==-1) {
                visit[v]=i;
              v=pre[v];
            }
            if(visit[v]!=i||v==root)
                continue;
            int u;
            for(u=pre[v];u!=v;u=pre[u])
                id[u]=res;
            id[v]=res++;
        }
        if(res==0)
            return sum;
        for(i=0;i<n;i++) {
            if(id[i]==-1)
                id[i]=res++;
        }
        for(i=0;i<yong;i++) {
            edge[i].w-=dis[edge[i].v];
            edge[i].u=id[edge[i].u];
            edge[i].v=id[edge[i].v];
        }
        n=res;root=id[root];
 }
 return sum;
}
int main(){
   int m,i,j,k,maxx,mm;
   while(scanf("%d%d",&n,&m)!=EOF) {
        yong=0;
        maxx=0;
        mm=m;//记录m
    while(m--) {
        scanf("%d%d%d",&i,&j,&k);
        maxx+=k;//记录最大值
        addedge(i,j,k);
    }
    maxx++;//增1
   for(i=0;i<n;i++)//会记录第几次加入的边
 addedge(n,i,maxx);//建立一个虚拟节点
 k=zhuliu(n);
    if(k==-1||k-maxx>=maxx)
        printf("impossible\n");
    else
    printf("%d %d\n",k-maxx,index-mm);//实际上的根节点是减去m
    printf("\n");
   }
return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值