题目链接:https://codeforces.com/contest/1242/problem/C
具体做法参照题解,记录一个子集当中dp的方法
https://cp-algorithms.com/algebra/all-submasks.html
代码:
#include<bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN=5005;
const int MAXM=(1<<15)+5;
ll sum[20];
bool vis[MAXN*15],ok[MAXM];
int x[16][MAXN],n[20],num[MAXN*15],pos[MAXN*15],stk[MAXN*15],dp[MAXM],pre[MAXM],l[16],r[16];
int top=0;
map<ll,int> id;
vector<int> E[MAXN*15],sv[MAXM];
void dfs(int now,int st)
{
if(vis[now])
{
int cir=0;
for(int i=top;i>=1;i--)
{
cir|=(1<<pos[stk[i]]);
if(stk[i]==now) break;
}
if(!ok[cir])
{
ok[cir]=true;
for(int i=top;i>=1;i--)
{
sv[cir].pb(stk[i]);
if(stk[i]==now) break;
}
}
return ;
}
if(st&(1<<pos[now])) return ;
st|=(1<<pos[now]);
vis[now]=true;stk[++top]=now;
for(int v:E[now])
{
dfs(v,st);
}
vis[now]=false;top--;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int k,idx=0;
ll S=0;
scanf("%d",&k);
for(int i=0;i<k;i++)
{
scanf("%d",&n[i]);
for(int j=1;j<=n[i];j++)
{
scanf("%d",&x[i][j]);
id[x[i][j]]=++idx;
num[idx]=x[i][j];
pos[idx]=i;
sum[i]+=x[i][j];
S+=x[i][j];
}
}
if(S%k!=0) return 0*puts("NO");
S/=k;
for(int i=1;i<=idx;i++)
{
ll v=S-(sum[pos[i]]-num[i]);
if(id.find(v)!=id.end())
{
E[i].pb(id[v]);
}
}
for(int i=1;i<=idx;i++)
dfs(i,0);
dp[0]=1;
for(int i=0;i<(1<<k);i++)
{
if(dp[i])
{
int rest=i^((1<<k)-1);
for(int j=rest;j;j=(j-1)&rest)
{
if(ok[j])
{
dp[i|j]=1;
pre[i|j]=i;
}
}
}
}
if(!dp[(1<<k)-1]) return 0*puts("NO");
int now=(1<<k)-1;
while(now)
{
int x=now-pre[now];
for(int i:sv[x])
{
int v=S-(sum[pos[i]]-num[i]);
l[pos[id[v]]]=v;
r[pos[id[v]]]=pos[i]+1;
}
now=pre[now];
}
puts("YES");
for(int i=0;i<k;i++)
printf("%d %d\n",l[i],r[i]);
return 0;
}