【题目链接】:click here~~
【题目大意】:
题意:在一个无向图中有 p 个点, m 条边,每个点有一个值 vi 。不断的删去度数小于2的点直到不能删为止。求新图中所有点个数为奇数的连通分量的点值的和。
1<p<10^4,1<m<10^5
【思路】删边考虑类似拓扑排序的写法,不过topsort是循环一遍1到n结点入度为0的结点,然后加入到队列中,这里只要改一下度数小于等于1,最后DFS 判断一下
挫挫的代码:
/*
* Problem: HDU No.5438
* Running time: 124MS
* Complier: G++
* Author: javaherongwei
* Create Time: 10:31 2015/9/18 星期五
*/
#include <stdio.h>
#include <queue>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e4+10;
typedef long long LL;
LL in[N];
LL val[N];
bool vis[N];
bool vis2[N];
vector <LL >G[N];
int n,m;
void topsort()
{
queue <LL >que;
while(!que.empty()) que.pop();
for(int i=1; i<=n; ++i){
if(in[i]<=1)
{
if(in[i]==1) que.push(i); //!!!
vis[i]=true;
}
}
while(!que.empty()){
LL u=que.front(); que.pop();vis[u]=true;
for(int i=0; i<G[u].size(); ++i){ // !!!i<G[u].size()!!!
LL k=G[u][i];
if(--in[k]<=1){
if(in[k]==1) que.push(k); //!!!
vis[k]=true;
}
}
}
}
LL dfs(int u) // dfs 传入第一个结点进行搜索遍历判断
{
queue<LL>que;
que.push(u);
vis2[u]=true;
LL sum=0;
LL len=0;
while(!que.empty()){
LL u=que.front();
que.pop();
sum+=val[u];
len++;
for(int i=0; i<G[u].size(); ++i){
LL k=G[u][i];
if(!vis[k]&&!vis2[k]){
que.push(k);
vis2[k]=true;
}
}
}
if(len&1) return sum;
else return 0;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(in,0,sizeof(in));
memset(val,0,sizeof(val));
memset(vis,false,sizeof(vis));
memset(vis2,0,sizeof(vis2));
for(int i=0; i<N; ++i) G[i].clear();
scanf("%d%d",&n,&m);
for(int i=1; i<=n; ++i) scanf("%lld",&val[i]);
for(int i=1; i<=m; ++i){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
in[u]++;
in[v]++;
}
topsort();
LL sum=0;
for(int i=1; i<=n; ++i){
if(!vis[i]&&!vis2[i]) sum+=dfs(i);
}
printf("%lld\n",sum);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5438 Ponds (拓扑排序+DFS)2015 ACM/ICPC Asia Regional Changchun Online
原文地址:http://blog.csdn.net/u013050857/article/details/48543153