HDU 6141 I am your Father!(最小树形图)

来源:互联网 发布:动物相机软件 编辑:程序博客网 时间:2024/06/05 07:52

Description

给出一个n个点m条边的有向图,求以1为根的最大费用有向树,在权值和相同的情况下选择n节点的父亲节点编号最小的方案,要求输出最小费用和n节点的父亲节点编号

Input

第一行一整数T表示用例组数,每组用例首先输入两整数nm分别表示点数和边数,之后m行每行输入三个整数x,y,w表示xy有一条权值为w的边(1n103,m104,1w100)

Output

对于每组用例,输出最大费用有向树的权值和和n节点的父亲节点编号

Sample Input

2
3 3
1 2 10
1 3 10
2 3 10
3 3
1 2 10
1 3 10
2 3 11

Sample Output

20 1
21 2

Solution

模版题,通过改变边权使得n节点父亲的字典序最小,把点编号0~n1,把每条边的边权乘上n,把un的边边权加上u,设新图的最小费用为ans,则最大费用为ansnn节点的父亲节点编号为ansnnans+1

Code

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map>#include<set>#include<ctime>using namespace std;typedef long long ll;#define INF 0x3f3f3f3f#define maxn 1111struct Edge{    int u,v,c;}edge[10*maxn];int pre[maxn],id[maxn],vis[maxn],in[maxn];int zhuliu(int root,int n,int m){    int ans=0,u,v;    while(1)    {        for(int i=0;i<n;i++)in[i]=INF;        for(int i=0;i<m;i++)            if(edge[i].u!=edge[i].v&&edge[i].c<in[edge[i].v])            {                pre[edge[i].v]=edge[i].u;                in[edge[i].v]=edge[i].c;            }        for(int i=0;i<n;i++)            if(i!=root&&in[i]==INF)                 return -1;        int res=0;        memset(vis,-1,sizeof(vis));        memset(id,-1,sizeof(id));        in[root]=0;        for(int i=0;i<n;i++)        {            ans+=in[i];            v=i;            while(vis[v]!=i&&id[v]==-1&&v!=root)            {                vis[v]=i;                v=pre[v];            }            if(id[v]==-1&&v!=root)            {                for(u=pre[v];u!=v;u=pre[u])                    id[u]=res;                id[v]=res++;            }        }           if(res==0)break;        for(int i=0;i<n;i++)            if(id[i]==-1)                id[i]=res++;        for(int i=0;i<m;i++)        {            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].c-=in[v];        }        n=res;        root=id[root];    }    return ans;}int T,n,m;int main(){    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].c);            edge[i].u--,edge[i].v--,edge[i].c*=-n;            if(edge[i].v==n-1)edge[i].c+=edge[i].u;        }        int ans=-zhuliu(0,n,m);        printf("%d %d\n",(ans+n-1)/n,(ans+n-1)/n*n-ans+1);    }    return 0;}