/*
拓扑+强联通
题意:
有n个池塘 m条管道连接 把连接管道小于2的池塘删掉
剩下的连通分量为奇数的池塘相加为多少
先拓扑删边+强连通判断奇偶
*/
# include <stdio.h>
# include <algorithm>
# include <iostream>
# include <vector>
# include <string.h>
# include <queue>
using namespace std;
const int MAXN = 20010;//点数
const int MAXM = 200010;//边数
struct Edge
{
int to,next;
} edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc
int Index,top;
int scc;//强连通分量的个数
bool Instack[MAXN];
int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc
//num数组不一定需要,结合实际情况
void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void Tarjan(int u)
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u]; i != -1; i = edge[i].next)
{
v = edge[i].to;
if( !DFN[v] )
{
Tarjan(v);
if( Low[u] > Low[v] )Low[u] = Low[v];
}
else if(Instack[v] && Low[u] > DFN[v])
Low[u] = DFN[v];
}
if(Low[u] == DFN[u])
{
scc++;
do
{
v = Stack[--top];
Instack[v] = false;
Belong[v] = scc;
num[scc]++;
}
while( v != u);
}
}
void solve(int N)
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
memset(num,0,sizeof(num));
Index = scc = top = 0;
for(int i = 1; i <= N; i++)
if(!DFN[i])
Tarjan(i);
}
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
int du[10010];
vector<int>g[10010];
void topsort(int n)
{
int top1=0;
int i,j;
while(top1<n)
{
top1++;
int flag=0;
for(i=1; i<=n; i++)
{
if(du[i]==1)
{
du[i]--;
flag=1;
break;
}
}
if(flag)
{
for(j=0; j<g[i].size(); j++)
{
du[g[i][j]]--;
}
}
else
break;
}
}
int main ()
{
int t;
__int64 a[10010];
int tmp[10010];
int b[100010],c[100010];
int n,m,i;
while(~scanf("%d",&t))
{
while(t--)
{
init();
scanf("%d%d",&n,&m);
for(i=1; i<=n; i++)
scanf("%I64d",&a[i]);
// memset(map,0,sizeof(map));
memset(du,0,sizeof(du));
for(i=1; i<=n; i++)
g[i].clear();
for(i=1; i<=m; i++)
{
scanf("%d%d",&b[i],&c[i]);
g[b[i]].push_back(c[i]);
g[c[i]].push_back(b[i]);
// map[b[i]][c[i]]=map[c[i]][b[i]]=1;
du[b[i]]++;
du[c[i]]++;
}
topsort(n);
// for(i=1;i<=n;i++)
// printf("%d %d\n",i,du[i]);
for(i=1; i<=m; i++)
{
if(du[b[i]]>=2&&du[c[i]]>=2)
{
addedge(b[i],c[i]);
addedge(c[i],b[i]);
}
}
solve(n);
// printf("%d\n",scc);
// for(i=1;i<=n;i++)
// printf("%d %d\n",i,Belong[i]);
memset(tmp,0,sizeof(tmp));
for(i=1; i<=scc; i++)
{
if((num[i]>1)&&num[i]%2)
{
tmp[i]=1;
}
}
__int64 sum=0;
for(i=1; i<=n; i++)
{
if(tmp[Belong[i]])
sum+=a[i];
}
printf("%I64d\n",sum);
}
}
return 0;
}
hdu 5438 Ponds(强连通)
最新推荐文章于 2020-11-13 17:16:00 发布