hdu5438(2015长春赛区网络赛1002)拓扑序+DFS

题意:给出一张无向图,每个节点有各自的权值,问在点数为奇数的圈中的点的权值总和是多少。

通过拓扑序的做法标记出所有非圈上的点,做法就是加每条边的时候将两点的入度都加一,然后将所有度数为1的点入队,删去它的所有边,即对没条边连的点度数减一,度数减为1继续入队,直到队列为空,入过队列的点都进行标记,表示该点不在圈上,那么剩余没有标记的点一定要么在圈上、要么是单点或自环。这时候只要对于每个没有访问过的节点,DFS遍历它的连通区域,记录点数和权值和,如果点数为奇数,则统计权值和。但是注意如果只有一个点,不能算作一个圈,所以除了判断点数是否奇数,还需要判断点数大于1。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<math.h>
 5 #include<queue>
 6 #include<iostream>
 7 typedef long long ll;
 8 using namespace std;
 9 
10 const int maxn=100050;
11 const int maxm=200050;
12 
13 int head[maxn],point[maxm],nxt[maxm],id[maxn],size,vis[maxn];
14 int v[maxn];
15 int n,m;
16 
17 void init(){
18     memset(head,-1,sizeof(head));
19     size=0;
20     memset(id,0,sizeof(id));
21     memset(vis,0,sizeof(vis));
22 }
23 
24 void add(int a,int b){
25     point[size]=b;
26     nxt[size]=head[a];
27     head[a]=size++;
28     id[b]++;
29     point[size]=a;
30     nxt[size]=head[b];
31     head[b]=size++;
32     id[a]++;
33 }
34 
35 void topo(){
36     queue<int>q;
37     for(int i=1;i<=n;++i)if(id[i]==1){
38         id[i]=-1;
39         q.push(i);
40     }
41     while(!q.empty()){
42         int u=q.front();
43         q.pop();
44         for(int i=head[u];~i;i=nxt[i]){
45             int j=point[i];
46             id[j]--;
47             if(id[j]==1){
48                 id[j]=-1;
49                 q.push(j);
50             }
51         }
52     }
53 }
54 
55 int nnum=0;
56 ll sum=0;
57 
58 void dfs(int s){
59     vis[s]=1;
60     nnum++;
61     sum+=v[s];
62     for(int i=head[s];~i;i=nxt[i]){
63         int j=point[i];
64         if(!vis[j]&&id[j]>0)dfs(j);
65     }
66 }
67 
68 int main(){
69     int T;
70     scanf("%d",&T);
71     while(T--){
72         scanf("%d%d",&n,&m);
73         init();
74         for(int i=1;i<=n;++i)scanf("%d",&v[i]);
75         while(m--){
76             int a,b;
77             scanf("%d%d",&a,&b);
78             add(a,b);
79         }
80         topo();
81         ll ans=0;
82         for(int i=1;i<=n;++i){
83             if(!vis[i]&&id[i]>0){
84                 sum=0;
85                 nnum=0;
86                 dfs(i);
87                 if(nnum%2&&nnum>1)ans+=sum;
88             }
89         }
90         cout<<ans<<endl;
91     }
92     return 0;
93 }
View Code
原文地址:https://www.cnblogs.com/cenariusxz/p/4806748.html