hdu6141-多校8&最小树形图&朱刘算法-I am your Father!

来源:互联网 发布:郝斌老师c语言笔记 编辑:程序博客网 时间:2024/05/17 08:43

http://acm.hdu.edu.cn/showproblem.php?pid=6141
比赛的时候根本没看那道题。
学习中。mark一下。
最小树形图 就是有向图的最小生成树。
一般用朱刘算法。
1 加入最小的边。如果存在孤立点,那么肯定不会有最小树形图。break
2 如果有 不包含root的环,对环进行缩点。
3 反复进行,直到没有环。
这里写图片描述
但这一道题还有不一样的地方,因为要求最大,所以全变成负数。
要 v-1这个点 的父节点尽可能小,所以 v-1的邻接边 全加上他的 父节点,
最后在后面的处理。。

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <ctime>#include <vector>#include <queue>#include <stack>#include <deque>#include <string>#include <map>#include <set>using namespace std;#define INF 0x3f3f3f3f#define LL long long#define fi first#define se second#define mem(a,b) memset((a),(b),sizeof(a))const int MAXV=1000+3;//最大顶点数const int MAXE=10000+3;//最大边数struct Edge{    int u, v;    int cost;}edge[MAXE];//边集int V,E;//顶点数,边数int pre[MAXV],id[MAXV],vis[MAXV];int in[MAXV];int zhuliu(int root)//返回最小花费{    int res=0;    while(true)    {        for(int i=0;i<V;++i)            in[i]=INF;        for(int i=0;i<E;++i)            if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v])            {                pre[edge[i].v]=edge[i].u;                in[edge[i].v]=edge[i].cost;//在所有点中寻找最小的。标定他的 弧头            }        for(int i=0;i<V;++i)            if(i!=root&&in[i]==INF)                return -1;//不存在最小树形图,因为有一个 孤立的点,怎么连都连不到        int tn=0;//新图结点数        for(int i=0;i<V;++i)        {            id[i]=-1;            vis[i]=-1;        }        in[root]=0;        for(int i=0;i<V;++i)        {            res+=in[i];            int v=i;            while(vis[v]!=i&&id[v]==-1&&v!=root)            {                vis[v]=i;                v=pre[v];// 向后遍历。vis是记录的 那条链的尾            }            if(v!=root&&id[v]==-1)            {                for(int u=pre[v];u!=v;u=pre[u])                    id[u]=tn;                id[v]=tn++;//求环、id是记录环的标号。缩点操作            }        }        if(tn==0)//没有有向环            break;        for(int i=0;i<V;++i)            if(id[i]==-1)                id[i]=tn++;// 自环        for(int i=0;i<E;i++)        {            int v=edge[i].v;            edge[i].u=id[edge[i].u];            edge[i].v=id[edge[i].v];            if(edge[i].u!=edge[i].v)                edge[i].cost-=in[v];            else swap(edge[i],edge[--E]);        }        V=tn;        root=id[root];    }    return res;}int main(){    int T;    scanf("%d", &T);    while(T--){          scanf("%d%d",&V,&E);          for(int i=0;i<E;i++){              scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].cost);              edge[i].u--,edge[i].v--;              edge[i].cost*=-1000;               if(edge[i].v==V-1)                   edge[i].cost+=edge[i].u;          }          int ans=zhuliu(0);          printf("%d %d\n",(-ans+999)/1000,(-ans+999)/1000*1000+ans+1);//最后加1,因为过程中处理的是 0-v-1的,所以要加1变为原来的、    }    return 0;}
原创粉丝点击