uestc 1651 Fill Numbers

题目链接:uestc 1651 Fill Numbers


这道题目确实是比较好,当时比赛的时候就一心想着高斯肖元,但是最坏的情况未知数最多为1000,而我的高斯肖元模版的时间复查度是O(n^3)几乎不可搞。。。因为如果高斯肖元的话,每个方程最多才2个未知数,一定可以得到更优的算法


把空格看作点,如果一行有 2 个空格,就在这两个空格之间连一条边,如果
列有2 个空格同理。这样最后形成的图可以分为以下几种连通块
 
1、一个孤立的点,说明这个点的值直接受所在行和所在列的约束,因此这
点可能有唯一解,也可能无解。
 
2、一条链,两个端点均为度为 1 的点,因此两个端点的值都可以通过所在
行或列唯一确定,我们从一端开始 dfs,依次求出链中每个点的值,最后判断一
下另一个端点的值是否合法即可。在这种情况下也是可能有唯一解,或者无解。  
 
3、一个环,仔细思考后可以发现,对一个环,只要存在一组特解,就一定
可以构造出无穷多组可行解,因此我们任取一点,任取一个初值开始 dfs,把环
拆成链,求出环中的一组特解,如果特解存在,则有无穷解,否则无解。
 
具体操作可以先从度为 1 的点开始 dfs,向空格填入对应的解,然后处理所
有度为0 的孤立点,最后判断有没有环,如果有环的环填入一组特解。最后统一
判断解是否合法

1、解合法&&无环    Unique
2、解合法&&有环    More than one
3、解不合法        No solution 


证明第3点其实很好证明:

  如果存在环的话,那么这个环内的定点个数就是偶数个,假如设 1 -> 2 -> 3 ->4 -> 1 是个环,而(1,2)的和值a,(2,3)和值为b,(3,4)和值为c,(4,1)和值为d, 那么只要满足

a+ c = b + d 就一定存在无穷多节,否者就无解


#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn=1010;
int n,m,a[maxn][maxn],row[maxn],col[maxn];
int x[maxn*2],y[maxn*2],degree[maxn*2];
vector g[maxn*2];
bool vis[maxn*2];

int cal(int u)
{
    int i;
    for(i=0;i=m){
       int tmp=0;
       for(int j=0;j


你可能感兴趣的:(numbers,ini,算法,c)