题意为给n个人,给出已完成和未完成的m1和m2场比赛
每场比赛赢的人加一分,输的人不扣分,已完成的会给出结果,问第一个人可不可以获胜
积分最搞的一个人或一群人都获胜
(赛场上贪了无数发,不出意外全寄了)
首先贪心的想,已完成比赛的分数我们无法确定,但未完成比赛我们可以选择让谁获胜
有1的比赛肯定让1获胜,这样全部进行完之后,1的分数就确定了
如果这个时候有人分数超过1了直接no
其他对于第i个人最多可以在赢 s[1]-s[i]场
我们可以把它看成网络流
a和b比赛之后流出去的流量为1
要么流向a要么流向b
每个人流出去的流量最多为s[i]-s[1]
然后源点向比赛连边,比赛向人连边,人向汇点连边
这样如果最大流是边满流,也就是源点流出去的水全到汇点了即为成立
否则为no
就比如这个样例吧
1的得分是2 2 3 4的得分都是1,他们都还能再赢一场,建出来的图就长这样
最大流明显等于流出去的流量,答案为yes
代码如下
#include <bits/stdc++.h>
#include <iomanip>
#define fer(i,a,b) for(int i=a;i<=b;i++)
#define der(i,a,b) for(int i=a;i>=b;i--)
#define int long long
#define pb push_back
#define pll pair<int,int>
#define ld double
#define x first
#define y second
using namespace std;
const int N = 1e5+10, M = N*2, INF = 1e8;
int S, T;
int h[N], e[M], f[M], ne[M], idx;
int d[N], cur[N];
void add(int a, int b, int c)
{
e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}
bool bfs()
{
queue<int> q;
memset(d, -1, sizeof d);
q.push(S);
d[S] = 0, cur[S] = h[S];
while (q.size())
{
auto t=q.front();
q.pop();
for (int i = h[t]; ~i; i = ne[i])
{
int ver = e[i];
if (d[ver] == -1 && f[i])
{
d[ver] = d[t] + 1;
cur[ver] = h[ver];
if (ver == T) return true;
q.push(ver);
}
}
}
return false;
}
int find(int u, int limit)
{
if (u == T) return limit;
int flow = 0;
for (int i = cur[u]; ~i && flow < limit; i = ne[i])
{
cur[u] = i; // 当前弧优化
int ver = e[i];
if (d[ver] == d[u] + 1 && f[i])
{
int t = find(ver, min(f[i], limit - flow));
if (!t) d[ver] = -1;
f[i] -= t, f[i ^ 1] += t, flow += t;
}
}
return flow;
}
int dinic()
{
int r = 0, flow;
while (bfs()) while (flow = find(S, INF)) r += flow;
return r;
}
int s[N],a[N];
int n,m1,m2;
int m;
signed main()
{
int cas;
cin>>cas;
while (cas--)
{
int m1,m2;
cin>>n>>m1>>m2;
S=n+m2+1;//源点编号
T=n+m2+2;//汇点编号
idx=0;
for (int i = 1; i <= n; i++)
s[i] = 0;
fer(i,0,n+m2+2) h[i] = -1 ;
for (int i = 1; i <= m1; i++)
{
int x, y, z;
cin>>x>>y>>z;
if (z == 1)
s[x]++;
else
s[y]++;
}
m=0;
fer(i,1,m2)
{
int x , y ;
cin >> x >> y ;
if(x == 1 || y == 1)
{
s[1] ++ ;
}
else
{
m++;//流出去的流量
add(n+i,x,1);//比赛向两个人连边
add(n+i,y,1);
add(S,n+i,1);//源点向比赛连边
}
}
bool fl=false;
fer(i,2,n){
if(s[i]>s[1]){
fl=true;
break;
}
add(i,T,s[1]-s[i]);//每个人向汇点连边
}
if(fl){
cout<<"NO\n";
continue;
}
if(dinic()==m) cout << "YES" << '\n' ;
else cout << "NO" << '\n' ;
}
}