hdu5438 dfs+拓扑排序+前向星

来源:互联网 发布:卖家淘宝客怎么设置 编辑:程序博客网 时间:2024/06/08 17:12

题目传送门: http://acm.hdu.edu.cn/showproblem.php?pid=5438


题目大意:有n个水池,m个管道,每个水池都有一个权值,Betty想要拆水池,只能拆度数为一的水池,他将一直拆下去直到不能拆为止,求含奇数个水池的连通图的总权值


思路:先用前向星建图,然后用类似拓扑排序的方式将可以拆的水池找出来,最后跑一遍dfs将有奇数个点的连通图给找出来


代码如下:

#include<bits/stdc++.h>using namespace std;#define   lowbit(x)     x&(-x)#define   lson          l,m,rt<<1#define   rson          m+1,r,rt<<1|1#define   ll            long long#define   ull           unsigned long long#define   mem(n,v)      memset(n,v,sizeof(n))#define   MAX           1000005#define   MAXN          2000005#define   PI            3.1415926#define   E             2.718281828459#define   opnin         freopen("text.in.txt","r",stdin)#define   opnout        freopen("text.out.txt","w",stdout)#define   clsin         fclose(stdin)#define   clsout        fclose(stdout)const int    INF    =   0x3f3f3f3f;const ll     INFF   =   0x3f3f;const double pi     =   3.141592653589793;const double inf    =   1e18;const double eps    =   1e-8;const ll     mod    =   1e9+7;const ull    mx     =   133333331;struct e{    int next;    int to;    int v;}edge[MAXN];int d[MAXN];int head[MAXN];int val[MAXN];int vis[MAXN];ll sum,Count,cnt;int n,m;void init(){    mem(val,0);    mem(vis,0);    mem(head,-1);    mem(d,0);    cnt = sum = Count = n = m = 0;}void makeedge(int u,int v){    edge[cnt].to = v;    edge[cnt].next = head[u];    head[u] = cnt++;}void getmap(int m){    int x,y;    int cnt = 1;    for(int i=1;i<=m;i++){        scanf("%d %d",&x,&y);        d[x]++;        d[y]++;        makeedge(x,y);        makeedge(y,x);    }}void toposort(){    queue<int>q;    for(int i=1;i<=n;i++){        if(d[i] == 1) q.push(i);    }    while(!q.empty()){        int id = q.front();        q.pop();        d[id] = 0;        for(int i=head[id];i != -1;i = edge[i].next){            d[edge[i].to]--;            if(d[edge[i].to] == 1) q.push(edge[i].to);        }    }}void dfs(int id){    vis[id] = 1;    sum += val[id];    Count++;    for(int i=head[id];i != -1;i = edge[i].next){        if(!vis[edge[i].to] && d[edge[i].to] > 1) dfs(edge[i].to);    }}void solve(){    scanf("%d %d",&n,&m);    for(int i=1;i<=n;i++){        scanf("%d",&val[i]);    }    getmap(m);    toposort();    ll ans = 0;    for(int i=1;i<=n;i++){        if(!vis[i] && d[i] > 1) dfs(i);        if(Count & 1) ans += sum;        sum = 0;        Count = 0;    }    cout << ans << endl;}int main(){    int kace;    cin >> kace;    while(kace--){        init();        solve();    }}


0 0
原创粉丝点击