HDU 5438 Ponds (拓扑排序+DFS)2015 ACM/ICPC Asia Regional Changchun Online

【题目链接】: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;
}


你可能感兴趣的:(拓扑排序,HDU,DFS)