hdu6201(spfa)

来源:互联网 发布:网络棋牌室代理 编辑:程序博客网 时间:2024/05/29 15:13


题意:

给你一棵树, 树上有点权, 要求选择起点S和终点T, 要求T-S-sum 最大, sum为S到T的边权。

思路:

根据题意就可以建图

建立源点和汇点。

源点连所有的树上点, 边权为 a[i], 所有树上点在连接 汇点, 边权为-a[i]. 然后在根据树建图。 

spfa跑个最长路即可。


#include<bits/stdc++.h>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int,int> P;#define fi first#define se second#define INF 0x3f3f3f3f#define clr(x,y) memset(x,y,sizeof x)#define PI acos(-1.0)#define ITER set<int>::iteratorconst int Mod = 1e9 + 7;const int maxn = 1e5 + 10;int val[maxn],n;struct Edge{int to,w,next;}edge[maxn << 2];int edge_num,head[maxn];void Init(){    clr(head,-1);edge_num = 0;}void add_edge(int x,int y,int z){edge[edge_num] = (Edge){y,z,head[x]};head[x] = edge_num ++;}int d[maxn],cnt[maxn];bool vis[maxn];void spfa(){    clr(d,-INF);clr(cnt,0);clr(vis,false);    queue<int>q;q.push(0);vis[0] = true;d[0] = 0;    while(! q.empty())    {        int u = q.front();q.pop();vis[u] = false;        for(int i = head[u];i != -1; i = edge[i].next)        {            int v = edge[i].to,w = edge[i].w;            if(d[v] < d[u] + w)            {                d[v] = d[u] + w;                if(!vis[v])                {                    vis[v] = true;q.push(v);if(++ cnt[v] > n)break;                }            }        }    }    printf("%d\n",d[n + 1]);}int main(){    int Tcase;scanf("%d",&Tcase);    while(Tcase --)    {        Init();        scanf("%d",&n);for(int i = 1;i <= n;i ++)scanf("%d",&val[i]);        for(int i = 1; i < n; i ++){int x,y,z;scanf("%d%d%d",&x,&y,&z);add_edge(x,y,-z);add_edge(y,x,-z);}        for(int i = 1;i <= n;i ++)add_edge(0,i,- val[i]);for(int i = 1; i <= n;i ++)add_edge(i,n + 1,val[i]);        spfa();    }    return 0;}


原创粉丝点击