zoukankan      html  css  js  c++  java
  • codeforce 240E

    /*

    最小树形图+保存路径

    第一次想错了,各种wa,tle后网上看资料,找到一篇错误的题解。。。

    最后用对着正解分析了一波,感觉对最小树形图又有了新的理解:最小树形图的精髓在于每张图更新的时间信息!

    第一次感觉到如此神奇的算法,解释分散在注释里了

    pass:交到cf上时加文件输入输出语句才能过

    */

    /*
    cf240e
    最小树形图:输出路径板子 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MAXN 100005
    #define MAXM 2000005
    #define ll long long 
    #define INF 0x7fffffff
    using namespace std;
    int pre[MAXN],vis[MAXN],in[MAXN],id[MAXN];
    int usedEdge[MAXN],preEdge[MAXN];
    struct Edge{
        int u,v,w,ww,id;
        Edge(){}
        Edge(int uu,int vv,int _w,int _ww,int ii):u(uu),v(vv),w(_w),ww(_ww),id(ii){}
    }edge[MAXM];
    struct Used{
        int pre,id;
    }cancle[MAXM];//保留每次更新图时被取消的边id 
    int zhuliu(int root,int n,int m){
        memset(usedEdge,0,sizeof usedEdge);
        int total=m,res=0;
        int u,v,w;
        while(1){
            for(int i=0;i<n;i++)in[i]=INF;
            for(int i=0;i<m;i++){
                u=edge[i].u,v=edge[i].v,w=edge[i].w;
                if(u!=v && w<in[v]){
                    in[v]=w;
                    pre[v]=u;
                    //记录这个顶点所在边的编号 !!!
                    preEdge[v]=edge[i].id;
                }
            }
            for(int i=0;i<n;i++)
                if (i!=root && in[i]==INF) return -1;
            
            int tn=0;
            memset(id,-1,sizeof id);
            memset(vis,-1,sizeof vis);
            in[root]=0;
            for(int i=0;i<n;i++){
                res+=in[i];
                v=i;
                //这条边被加入到当前图集合E中,这个点所在的边使用次数+1 !!!!
                if(i!=root) usedEdge[preEdge[i]]++;
                while(v!=root && id[v]==-1 && vis[v]!=i){
                    vis[v]=i;
                    v=pre[v];
                }
                if(id[v]==-1 && v!=root){
                    for(u=pre[v];u!=v;u=pre[u])
                        id[u]=tn;
                    id[v]=tn++;
                }
            } 
            if(tn==0) break;
            for(int i=0;i<n;i++)
                if(id[i]==-1) id[i]=tn++;
            
            //准备更新旧图 
            for(int i=0;i<m;i++){
                u=edge[i].u,v=edge[i].v;
                edge[i].u=id[u],edge[i].v=id[v];
                if(id[u]!=id[v]){
                    edge[i].w-=in[v];
                    //将该边在旧图中的编号取消 
                    cancle[total].id=edge[i].id;
                    cancle[total].pre=preEdge[v]; 
                    ///将这条边id重新编号
                    edge[i].id=total++;             
                }
            }
            n=tn;
            root=id[root];
        }
        //统计新建立(被重新编号)的边 !!!因为每重新编号一条边,就说明有一条边被取消一次,一因此需要将那条变得增加量也取消 
        //为什么要倒着往回遍历?因为必须沿着最终形成图的状态回溯逐步回溯到原图,找到边原始的id  
        //肯定是新建立的边导致了之前的边被取消掉, 
        for(int i=total-1;i>=m;i--)
            if(usedEdge[i]){//如果这条边被使用过(如果一条边仅仅是被重新编号而未被使用过,即只参与了边权值的改变但没有真正加入到某一次循环图中去,那么和其相关的边不用被取消) 
                usedEdge[cancle[i].id]++;//
                usedEdge[cancle[i].pre]--;//把之前加的减掉 
            }
        return res;
    } 
    
    int main(){
        int n,m;
        while(~scanf("%d%d",&n,&m)){
            for(int i=0;i<m;i++){
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                u--;v--;
                edge[i]=Edge(u,v,w,w,i);
            }
            int root=0;
            int ans=zhuliu(root,n,m);
            if(ans==-1 || ans==0)
                printf("%d
    ",ans); 
            else {
                printf("%d
    ",ans);
                for(int i=0;i<m;i++)
                    if(edge[i].ww==1 && usedEdge[i])
                        printf("%d ",i+1);
                printf("
    ");
            }
        }    
        return 0;
    } 
  • 相关阅读:
    解决 网上下载的例子 My Mac 64bit 不能运行的问题
    给XMLHttpRequest设置超时时间
    MSN常见登录错误解决方法
    javascript keycode大全
    禁止手动修改FileUpload控件
    "ORA00942: 表或视图不存在 "的原因和解决方法
    梅花雪控件树应用实例----异步绑定自定义表结构的用户部门表
    菜鸟学模式三 观察者模式
    菜鸟学模式一 序言
    利用js去除打印时的页眉页脚
  • 原文地址:https://www.cnblogs.com/zsben991126/p/9807903.html
Copyright © 2011-2022 走看看