GYM106007D-Master of the Arena

GYM106007D-Master of the Arena

题目大意

\(n\) 个战士,给你一个 \(n*n\) 的矩阵,\(a_{ij}==1\) 表示 \(i\) 战士一定可以打败 \(j\) 战士; \(a_{ij}==0\) 表示 \(i\) 战士一定输给 \(j\) 战士; \(a_{ij}==?\) 表示结果尚未确定,你可以自行选择。

你必须安排 \(n-1\) 场一对一的比赛,最终只有一名战士保持不败,这个人必须是标号为 \(1\) 的战士。一个战士可以参加多场比赛直到被淘汰。如果无法做到输出 \(No\) ,否则输出 \(Yes\) 并且按比赛顺序输出 \(n-1\)\(a,b\) 表示在这场比赛中 \(a\) 击败了 \(b\)

题解

对于确定的击败,可以建立一条有向边,对于 \(?\) 建立一条无向边。然后从 \(1\) 开始 \(dfs\) ,可以遍历所有的结点,建立出一棵树,那就存在合法的答案,否则便不存在答案。

对于合法的答案,按照树的形状,从叶子节点开始按照拓扑序输出边即可。

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define umap unordered_map
#define endl '\n'
using namespace std;
using i128 = __int128;
const int mod =1e9+7;
template <typename T>void read(T&x){
    x=0;int f = 1;
    char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    x*=f;
}
template <typename T>void print(T x) {
     if (x < 0) { putchar('-'); x = -x; }
     if (x > 9) print(x / 10);
     putchar(x % 10 + '0');
}
#define int long long
const int N=500005;
const int M=2000005;
vector<int> fa(2000);
vector<string> s(2000);
vector<int> deg(2000);
vector<int> vis(2000);
int n;
void dfs(int u,int f)
{
	fa[u]=f;
	deg[f]++;
	for(int i=1;i<=n;i++)
	{
		if(fa[i]!=i) continue;
		if(s[u-1][i-1]=='1'||s[u-1][i-1]=='?')
		{
			dfs(i,u);
		}
	}
}

void dfs2(int u)
{
	cout<<fa[u]<<" "<<u<<endl;
	vis[u]=1;
	if(fa[u]!=1&&--deg[fa[u]]==0) dfs2(fa[u]);
}
inline void solve()
{

	cin>>n;

	for(int i=0;i<n;i++) 
	{
		cin>>s[i];
	}
	for(int i=0;i<=n;i++) fa[i]=i,deg[i]=0,vis[i]=0;
	dfs(1,0);
	for(int i=1;i<=n;i++)
	{
		if(fa[i]==i)
		{
			cout<<"No"<<endl;
			return;
		}
	}
	cout<<"Yes"<<endl;
	for(int i=2;i<=n;i++)
	{
		if(deg[i]==0&&vis[i]!=1)
		{
			dfs2(i);
		}
	}
}

signed main()
{
	ios;
	int T=1;
	cin>>T;
	for(;T--;) solve();
	return 0;
}
posted @ 2025-11-20 12:36  NDAKJin  阅读(4)  评论(0)    收藏  举报