@xiaoziyao
        
        2021-04-20T03:11:24.000000Z
        字数 2768
        阅读 1475
    解题报告
P7515 [省选联考 2021 A 卷] 矩阵游戏解题报告:
给定大小为的矩阵,求生成任意一个满足条件的满足:
保证,。
可能是暗中送我退役的一道题,我要是把这个思路想下去做掉这道题,那我剩下的题用头打都能进队啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!
技不如人,肝败吓疯。
首先不考虑,并钦定,不难发现可以生成一组解。
我们考虑通过调整某些位置的权值使得最后的解权值满足限制。
发现对某一行交替后的解仍然满足矩阵的限制;同理,对某一列交替后的解也仍然满足矩阵的限制。
不难发现任意一组解都可以被这样表示出来:
再考虑这一限制,不难发现把序列与序列看做未知量之后可以对其进行差分约束。
但是对于同号的不等式是很难进行差分约束的,考虑定义,
然后再次带入上面的解可以得到一个很优美的形式:
这样就可以进行差分约束了,复杂度:。
Bellman Ford被卡常了(需要特判才能过),迫不得已用了spfa/kk
#include<stdio.h>#include<queue>#include<vector>#define inf 10000000000000000using namespace std;const int maxn=305,maxm=maxn*maxn*2;int T,n,m,e;int a[maxn][maxn],b[maxn][maxn],vis[maxn<<1],tot[maxn<<1];vector<int>v[maxn<<1],w[maxn<<1];long long dis[maxn<<1];queue<int>q;inline void add(int x,int y,int z){v[x].push_back(y),w[x].push_back(z);}inline void limit(int x,int y,int v){add(x,y,v);//v+x-y>=0add(y,x,1000000-v);//v+x-y<=1000000}int spfa(){while(!q.empty())q.pop();for(int i=1;i<=n+m;i++)dis[i]=inf,tot[i]=0,vis[i]=0;dis[1]=0,vis[1]=1,q.push(1);while(!q.empty()){int x=q.front();tot[x]++;if(tot[x]>n+m)return 1;q.pop();for(int i=0;i<v[x].size();i++){int y=v[x][i],z=w[x][i];if(dis[y]>dis[x]+z){dis[y]=dis[x]+z;if(vis[y]==0)vis[y]=1,q.push(y);}}vis[x]=0;}return 0;}inline int calc(int x,int y){return a[x][y]+(int)(((x+y)&1)? (dis[n+y]-dis[x]):(dis[x]-dis[n+y]));}int main(){scanf("%d",&T);while(T--){e=0;scanf("%d%d",&n,&m);for(int i=1;i<n;i++)for(int j=1;j<m;j++)scanf("%d",&b[i][j]);for(int i=2;i<=n;i++)for(int j=2;j<=m;j++)a[i][j]=b[i-1][j-1]-a[i-1][j-1]-a[i-1][j]-a[i][j-1];for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){if((i+j)&1)limit(n+j,i,a[i][j]);else limit(i,n+j,a[i][j]);}if(spfa()){puts("NO");for(int i=1;i<=n+m;i++)v[i].clear(),w[i].clear();continue;}puts("YES");for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)printf("%d%c",calc(i,j),j==m? '\n':' '),a[i][j]=0;for(int i=1;i<=n+m;i++)v[i].clear(),w[i].clear();}return 0;}
省选联考A卷全部题解可见:2021省选联考A卷解题报告
