hdu 6141 I am your Father!(最小树形图+权值编码)

来源:互联网 发布:ubuntu 安装terminal 编辑:程序博客网 时间:2024/06/07 01:24
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6141

思路:

1.求解一有向树,使得权值最大。最小树形图边权取反即可。

2.要求编号为n的节点的父亲字典序最小:将节点的编号引入边权值中,同时为了避免节点编号的影响比初始权值影响大,将每个边权乘n(即-n*w),这样即使边权值变化一单位,其影响程度也大于点编号的影响,即只有边权值相同时顶点编号起作用。若点u连接节点n,则边权值再加上u(即-n*w+u)。最终结果为-n*sigma(w)+u。

3.取反ret=n*sigma(w)-u,此时若直接除以n,则会使最终结果减少。所以,将其加上n,此时0<n-u<n,将n*sigma(w)+n-u除以n(整除),结果即为sigma(w),记为ans。

4.顶点标号:u=n*ans-ret。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define debugusing namespace std;typedef long long LL;const int maxn=1e3+50;const int INF=0x3f3f3f3f;struct Node{    int oldu,oldv;    int u,v,w;};int n,m,rt;int in[maxn];Node e[maxn*10];int pre[maxn],ID[maxn],vis[maxn];int Directed_MST(int root,int n,int m){    int oldroot=root;    int ret=0;    for(;;)    {        for(int i=1; i<=n; i++) in[i]=INF;        for(int i=1; i<=m; i++)        {            int u=e[i].u,v=e[i].v;            if(u!=v&&e[i].w<in[v])            {                pre[v]=u,in[v]=e[i].w;                if(e[i].oldu==oldroot) rt=e[i].oldv;            }        }        for(int i=1; i<=n; i++)        {            if(i==root) continue;            if(in[i]==INF) return -1;        }        int nn=0;        memset(ID,-1,sizeof(ID));        memset(vis,-1,sizeof(vis));        in[root]=0;        for(int i=1; i<=n; i++)        {            ret+=in[i];            int v=i;            while(v!=root&&ID[v]==-1&&vis[v]!=i)            {                vis[v]=i;                v=pre[v];            }            if(v!=root&&ID[v]==-1)            {                ID[v]=++nn;                for(int u=pre[v]; u!=v; u=pre[u]) ID[u]=nn;            }        }        if(nn==0) break;        for(int i=1; i<=n; i++)        {            if(ID[i]==-1) ID[i]=++nn;        }        for(int i=1; i<=m; i++)        {            int u=e[i].u;            int v=e[i].v;            e[i].u=ID[u];            e[i].v=ID[v];            if(u!=v) e[i].w-=in[v];        }        n=nn;        root=ID[root];    }    return ret;}int main(){#ifdef debu    freopen("in.txt","r",stdin);#endif // debug    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        for(int i=1; i<=m; i++)        {            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);            e[i].oldu=e[i].u;            e[i].oldv=e[i].v;            e[i].w=-n*e[i].w;            if(e[i].v==n) e[i].w+=e[i].u;        }        int ret=-Directed_MST(1,n,m);        int ans=(ret+n)/n;        int ansu=-ret+n*ans;        printf("%d %d\n",ans,ansu);    }    return 0;}



原创粉丝点击