【HDU 5438】Ponds
题意
不断删去度数为1的点,最后求有奇数个点的联通块的权值之和。
分析
存边的时候,要头尾都存这个边。用dfs或者队列删点,再用并查集或者dfs确定联通块,然后统计联通块的点数,最后累加。
我自己写的超时,然后参考了网上的题解。真郁闷。
代码
并查集
#include<cstdio> #include<queue> #include<vector> #define ll long long using namespace std; const int N = 1e4 + 10; ll v[N]; ll s[N]; int n,m,e[N],f[N],cn[N]; vector<int> d[N]; int find(int a) { return f[a]==a?a:find(f[a]); } void unite(int a,int b) { a=find(a),b=find(b); if(a!=b) f[a]=b; } void add(int a,int b) { e[a]++; e[b]++; d[a].push_back(b); d[b].push_back(a); unite(a,b); } void del() { queue<int>q; for(int i=1; i<=n; i++) if(e[i]==1) q.push(i); while(!q.empty()) { int r=q.front(); q.pop(); for(int j=0; j<d[r].size(); j++) { int w=d[r][j]; e[w]--; if(e[w]==1)q.push(w); } } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf("%lld",&v[i]); e[i]=s[i]=cn[i]=0; f[i]=i; d[i].clear(); } for(int i=1; i<=m; i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); } del(); for(int i=1; i<=n; i++) { if(e[i]>1) { int a=find(i); s[a]+=v[i]; cn[a]++; } } ll ans=0; for(int i=1; i<=n; i++) { if (f[i]==i && cn[i]&1) { ans+=s[i]; } } printf("%lld\n",ans); } return 0; }
dfs确定联通块
#include<cstdio> #include<queue> #include<vector> #define ll long long using namespace std; const int N = 1e4 + 10; ll v[N]; int n,m,e[N],vis[N]; ll ct,sum; vector<int> d[N]; void add(int a,int b) { e[a]++; e[b]++; d[a].push_back(b); d[b].push_back(a); } void dfs(int a) { vis[a]=1; sum+=v[a]; ct++; for(int i=0; i<d[a].size(); i++) { int w=d[a][i]; if(!vis[w]) dfs(w); } } void del() { queue<int>q; for(int i=1; i<=n; i++) { if(e[i]==1) q.push(i); if(e[i]==0) vis[i]=1; // 别忘了度为0的点 } while(!q.empty()) { int r=q.front(); vis[r]=1; q.pop(); for(int j=0; j<d[r].size(); j++) { int w=d[r][j]; e[w]--; if(e[w]==1)q.push(w); } } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf("%lld",&v[i]); e[i]=vis[i]=0; d[i].clear(); } for(int i=1; i<=m; i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); } del(); ll ans=0; for(int i=1; i<=n; i++) { sum=ct=0; if(!vis[i]) dfs(i); if(ct&1)ans+=sum; } printf("%lld\n",ans); } return 0; }
┆凉┆暖┆降┆等┆幸┆我┆我┆里┆将┆ ┆可┆有┆谦┆戮┆那┆ ┆大┆始┆ ┆然┆
┆薄┆一┆临┆你┆的┆还┆没┆ ┆来┆ ┆是┆来┆逊┆没┆些┆ ┆雁┆终┆ ┆而┆
┆ ┆暖┆ ┆如┆地┆站┆有┆ ┆也┆ ┆我┆ ┆的┆有┆精┆ ┆也┆没┆ ┆你┆
┆ ┆这┆ ┆试┆方┆在┆逃┆ ┆会┆ ┆在┆ ┆清┆来┆准┆ ┆没┆有┆ ┆没┆
┆ ┆生┆ ┆探┆ ┆最┆避┆ ┆在┆ ┆这┆ ┆晨┆ ┆的┆ ┆有┆来┆ ┆有┆
┆ ┆之┆ ┆般┆ ┆不┆ ┆ ┆这┆ ┆里┆ ┆没┆ ┆杀┆ ┆来┆ ┆ ┆来┆