题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5438
1 7 7 1 2 3 4 5 6 7 1 4 1 5 4 5 2 3 2 6 3 6 2 7
21
解题思路:首先 你要考虑怎么,保证它是一个圈。这样就想到采用拓扑排序的方法,去掉所有入度<2的点。再就是判断这个圈是否含有奇数个点,采用深搜的方法将每个点做一次起始点,对其进行搜索计数!
详见代码。
#include <iostream> #include <cstdio> #include <vector> #include <cstring> using namespace std; #define N 10010 #define ll long long ll val[N],V; int vis[N];//判断这个点有没有删掉 int Vis[N];//判断这个点有没有做为起点进行搜索过 int indir[N],k; vector<int>G[N]; void dfs(int st) { k++; V+=val[st]; for (int i=0; i<G[st].size(); i++) { if (!Vis[G[st][i]]&&!vis[G[st][i]]) { Vis[G[st][i]]=1; dfs(G[st][i]); } } } int main() { int t,a,b; scanf("%d",&t); while (t--) { int n,m; memset(vis,0,sizeof(vis)); memset(Vis,0,sizeof(Vis)); memset(val,0,sizeof(val)); memset(indir,0,sizeof(indir)); scanf("%d%d",&n,&m); for (int i=1; i<=n; i++) G[i].clear(); for (int i=1; i<=n; i++) scanf("%lld",&val[i]); for (int i=1; i<=m; i++) { scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); indir[a]++; indir[b]++; } while (1) { int i; for (i=1; i<=n; i++) { if (indir[i]<2&&!vis[i]) { vis[i]=1; for (int j=0; j<G[i].size(); j++) { if (!vis[G[i][j]]) indir[G[i][j]]--; } break; } } if (i>n) break; } ll ans=0; for (int i=1; i<=n; i++) { if (!Vis[i]&&!vis[i]) { k=0; V=0; Vis[i]=1; dfs(i); if (k%2==1) ans+=V; } } printf ("%lld\n",ans); } return 0; }