#include <iostream>
#include <queue>
using namespace std;
const int maxN=105;
const int inf=0xffff;
bool g[maxN][maxN];//关系数组,初始图
int edge[maxN][maxN];//生成图的邻接权矩阵
int n,m;//顶点数和边数
int cnt;//测试数目
int ans;
bool visited[maxN];
int father[maxN];
void Ford_Fulkerson()
{
while(1)
{
//一次大循环,找到一条可能的增广路径
queue <int> q;
memset(visited, 0, sizeof(visited));
memset(father, -1, sizeof(father));
int now;
visited[0] = true;
q.push(0);
while(!q.empty())//广度优先
{
now = q.front();
q.pop();
if(now == n-1) break;
for(int i=0; i<n+n-2; i++) //生成图定点数
{
//每次父亲节点都要更新,权值减为0的边就不算了.
if(edge[now][i] && !visited[i])
{
father[i] = now;
visited[i] = true;
q.push(i);
}
}
}
//可能的增广路不存在了
if(!visited[n-1]) break; //终点标号
int u, min = inf;
for(u=n-1; u; u=father[u])//找出权值最小的边
{
if(edge[father[u]][u] < min)
min = edge[father[u]][u];
}
//减去最小权值
for(u=n-1; u; u=father[u])
{
//前向弧减去
edge[father[u]][u] -= min;
//后向弧加上
//存在圆环,这句话关键
edge[u][father[u]] += min;
}
//当前增广路径增加的流
ans+=min;
}
}
int main()
{
freopen("5.3.in","r",stdin);
cin>>cnt;
int s,e,temp;
while(cnt--)
{
ans=0;
memset(g,0,sizeof(g));
memset(edge,0,sizeof(edge));
cin>>n>>m;
n+=1;
for(int i=1;i<=n-2;i++)
{
int num;//狙击兵个数
cin>>num;
//将点分成一条边
edge[i][i+n-1]=num;
}
for(int i=0;i<m;i++)
{
cin>>s>>e;
if(s>e)
{
temp=s;
s=e;
e=temp;
}
g[s][e]=true;
if(s!=0&&e!=n-1) //不含有起点或终点,设定为双向边
g[e][s]=true;
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(g[i][j])
{
if(i==0) edge[i][j]=inf;
if(i!=0) edge[i+n-1][j]=inf;
}
}
Ford_Fulkerson();
cout<<ans<<endl;
}
return 0;
}
本文发布于:2024-01-29 16:10:51,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170651585216489.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |