化简分析,先加一个A(n,4) 然后减去对答案没有贡献以及负贡献,考虑对答案没有贡献的四元组,此四元组中存在且只存在一个点有两条边
从他出发,对答案贡献-1的点,存在恰好两个点,分别有两条边从他们出发。
化最后发现只和点的出度的平方或者说(C(deg[i],2)) 因为sum(deg[i])为定值有关
化最后可以用费用流做
#include<bits/stdc++.h>
using namespace std;
struct MCMF{
static const int maxn=200+2+200*200,maxm=maxn*5;
struct star{int v,nex;int c,w;} edge[maxm<<1];
int head[maxn],cnt,n;
int inq[maxn],pre[maxn];
int dist[maxn];
void ini(int n){
cnt=-1;this->n=n;
for(int i=0;i<=n;i++) head[i]=-1;
}
void add_edge(int u, int v, int c, int w){
// cout<<" "<<u<<" "<<v<<" "<<c<<" "<<w<<endl;
edge[++cnt]=star{v,head[u],c, w}; head[u]=cnt;
edge[++cnt]=star{u,head[v],0,-w}; head[v]=cnt;
}
void minCostMaxFlow(int s, int t,int&flow,int&cost){
flow=cost=0;
while(true){
for(int i=0;i<=n;i++) dist[i]=1e9;
queue<int>que; que.push(s);
inq[s]=1; dist[s]=0;
while(!que.empty()){
int u=que.front();
que.pop(); inq[u]=0;
for(int i=head[u];~i;i=edge[i].nex){
int v=edge[i].v;
int c=edge[i].c,w=edge[i].w;
// if(c>eps&&dist[v]>dist[u]+w+eps){
if(c>0&&dist[v]>dist[u]+w){
dist[v]=dist[u]+w;
pre[v]=i;
if(!inq[v]) que.push(v);
inq[v]=1;
}
}
}
if(dist[t]==1e9) return ;
int addf=1e9;
for(int x=t;x!=s;x=edge[pre[x]^1].v) addf=min(addf,edge[pre[x]].c);
for(int x=t;x!=s;x=edge[pre[x]^1].v){
edge[pre[x]].c-=addf;
edge[pre[x]^1].c+=addf;
}
flow+=addf;
cost+=dist[t]*addf;
}
}
} g;
/*
ans=A(n,4)-sum( C(2,deg[i]) )*8*(n-3)
*/
char graph[205][205];
int deg[205];
int main(){
int T; scanf("%d",&T);
while(T--){
int n; scanf("%d",&n);
for(int i=1;i<=n;i++) deg[i]=0;
for(int i=1;i<=n;i++) scanf("%s",graph[i]+1);
int tot=n;
int s=++tot;
int t=++tot;
for(int i=1;i<=n;i++) {
for(int j=i+1;j<=n;j++){
if(graph[i][j]=='1') deg[i]++;
else if(graph[i][j]=='0') deg[j]++;
}
}
int ans=0;
for(int i=1;i<=n;i++) ans+=deg[i]*(deg[i]-1)/2;
g.ini(n+2+n*(n-1)/2);
for(int i=1;i<=n;i++) {
for(int j=i+1;j<=n;j++){
if(graph[i][j]=='2'){
g.add_edge(s,++tot,1,0);
g.add_edge(tot,i,1,0);
g.add_edge(tot,j,1,0);
g.add_edge(i,t,1,deg[i]);//C(n+1,2)-C(n,2)=n
g.add_edge(j,t,1,deg[j]);
deg[i]++;
deg[j]++;
}
}
}
int cost,flow;
g.minCostMaxFlow(s,t,cost,flow);
printf("%d\n", n*(n-1)*(n-2)*(n-3)-(ans+flow)*8*(n-3));
}
}