2015多校第8场 HDU 5385 贪心,最小生成树

来源:互联网 发布:手机淘宝怎么改差评 编辑:程序博客网 时间:2024/06/10 05:33

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5385

题意:给了一个有向连通图,要给图中的每一条边加一个权值,使得满足dis[1]<dis[2]<dis[x]>dis[x+1]>dis[n]成立,x可以取到n。

解法:官方题解


如果我们知道每个点的dis值和最短路径树的话,方案是很容易构造的

我们可以采取贪心做法,一开始将1号点作为最短路径树的根,然后左边从2开始,右边从n开始,只要之前加入的点有边连向他们就加入

这样一个点加入的时间就是他的dis值,最短路径树上的父亲也可以确定,于是输出时非树边长度为n,树边长度为两个端点dis之差


#include <bits/stdc++.h>using namespace std;const int maxn = 1e5+10;int head[maxn], edgecnt;void init(){    edgecnt=0;    memset(head,-1,sizeof(head));}struct edge{    int to,next;}E[maxn];void add(int u, int v){    E[edgecnt].to = v, E[edgecnt].next = head[u], head[u] = edgecnt++;}struct node{    int u,v;}q[maxn];int T,n,m,dis[maxn],vis[maxn];int main(){    scanf("%d", &T);    while(T--)    {        init();        memset(vis, 0, sizeof(vis));        scanf("%d %d", &n,&m);        for(int i=1; i<=m; i++){            int u,v;            scanf("%d %d", &u,&v);            q[i].u = u, q[i].v = v;            add(u, v);        }        vis[1] = vis[n] = 1;        int l=1,r=n,u;        for(int i=1; i<=n; i++){            if(vis[l]==0) u=r--;            else u=l++;            dis[u] = i;            for(int j=head[u]; ~j; j=E[j].next){                int v=E[j].to;                vis[v]=1;            }        }//        for(int i=1; i<=n; i++){//            printf("%d ", dis[i]);//        }//        printf("\n");        for(int i=1; i<=m; i++){            if(dis[q[i].u] < dis[q[i].v]){                printf("%d\n", dis[q[i].v]-dis[q[i].u]);            }            else{                printf("%d\n", n);            }        }    }    return 0;}


原创粉丝点击