【题目链接】: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;
}
下午试了一下邻接表写法,比用vector存边耗时快一点了,109ms
代码:
/*
* Problem: HDU No.5438
* Running time: 109MS
* Complier: G++
* Author: javaherongwei
* Create Time: 14:51 2015/9/18 星期五
*/
#include <stdio.h>
#include <queue>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+10;
struct node{
int to,next;
}edge[N<<1];
int tot,head[N];
int n,m;
bool vis[N];
int deg[N];
int val[N];
void init(){
tot=0;
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
memset(deg,0,sizeof(deg));
}
void add_edge(int u,int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void topsort()
{
queue<int >que;
while(!que.empty()) que.pop();
for(int i=1; i<=n; ++i)
if(deg[i]<=1) que.push(i);
while(!que.empty()){
int u=que.front();que.pop();vis[u]=true;
for(int i=head[u]; i!=-1; i=edge[i].next){
int k=edge[i].to;
if(!vis[k]){
if(--deg[k]<=1) que.push(k);
}
}
}
}
LL len,sum;
void dfs(int u)
{
vis[u]=true;
len++;
sum+=val[u];
for(int i=head[u]; i!=-1; i=edge[i].next){
int k=edge[i].to;
if(!vis[k]){
dfs(k);
}
}
}
int main()
{
int t;scanf("%d",&t);
while(t--){
init();
scanf("%d%d",&n,&m);
for(int i=1; i<=n; ++i) scanf("%d",&val[i]);
while(m--){
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
deg[u]++;deg[v]++;
}
topsort();
LL ans=0;
for(int i=1; i<=n; ++i){
if(!vis[i]){
len=0;
sum=0;
dfs(i);
if(len&1) ans+=sum;
}
}
printf("%lld\n",ans);
} return 0;
}