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