给定一个图,让你把连通度小于2的点都给删掉。然后把联通块点数为奇数的联通块对应的权重加起来,问你结果是多少。。
一开始以为是 割点,没错,是割点。。。。。后来打对了模板了发现不是割点qwq。。
然后又感觉一次判断连通度就可以了。。
wawawawawa
中间有一点微微的感觉是拓扑排序的赶脚,又想用反向边那一套来整,后来直接放弃了。。。
知道了拓扑后,第二天用拓扑排序。又是wa
众所周知拓扑不能搞得环,如果是有向图就是回路。
所以他会留下回路,那么问题来了,在拓扑后,所有的度都会是0么。。
答案是不是。。
我竟然以为是,。。。。
对于最外面的点,是-1,中间的是0,和环连接的那个点1.
所以在判断的时候,只要参加过拓扑排序的多应该vis掉。然后再整。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
const int maxn=1e5+5;
using namespace std;
int sum;
long long all;
vector<int>G[maxn];
bool vis[maxn];
long long v[maxn];
int indgree[maxn];
int dfs(int a)
{ for(int i=0;i<G[a].size();i++)
{ if(!vis[G[a][i]])
{ sum++;
all+=v[G[a][i]];
vis[G[a][i]]=true;
dfs(G[a][i]);
}
}
return 0;
}
int main()
{ int m,n;
int a,b;
int t;
cin>>t;
while(t--)
{ scanf("%d%d",&m,&n);
for(int i=0;i<maxn;i++)
G[i].clear();
memset(indgree,0,sizeof(indgree));
memset(v,0,sizeof(v));
memset(vis,false,sizeof(vis));
for(int i=1;i<=m;i++)
scanf("%lld",&v[i]);
for(int i=1;i<=n;i++)
{ scanf("%d%d",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
indgree[a]++;
indgree[b]++;
}
queue<int>q;
for(int i=1;i<=m;i++)
{ if(indgree[i]==1)
{ vis[i]=true;
q.push(i);}
}
while(!q.empty())
{ int u=q.front();
q.pop();
for(int i=0;i<G[u].size();i++)
{ int s=G[u][i];
indgree[s]--;
indgree[u]--;
if(indgree[s]==1)
{ vis[s]=true;
q.push(s);
}
}
}
/*最开始的时候是拓扑完判断度是否为0.。。当然错了。
度可以是 -1,0,1;
*/
long long ans=0;
for(int i=1;i<=m;i++)
{ if(!vis[i])
{ sum=1;
vis[i]=true;
all=v[i];
//cout<<i<<endl;
dfs(i);
if(sum%2==1&&sum>1)
{ ans+=all;
}
}
}
cout<<ans<<endl;
}
return 0;
}