Codeforces Gym 101174 I The White Rabbit Pocket Watch 模线性方程组

#include<stdio.h>
#include <math.h>
#include <algorithm>
#include <math.h>
#include <string.h>
using namespace std;
const int mod=13;
int a[510][200*100+10];
int x[510],id[201][201];
inline int gcd(int a,int b)
{
    while(b!=0)
    {
        int t=b;
        b=a%b;
        a=t;
    }
    return a;
}
inline int lcm(int a,int b)
{
    return a/gcd(a,b)*b;
}
#define LL long long
LL inv(LL a,LL m)
{
    if(a==1)return 1;
    return inv(m%a,m)*(m-m/a)%m;
}
inline int meow(int x)
{
    return (x%mod+mod)%mod;
}
int gauss(int equ,int var)
{
    int max_r,col,k;
    for(k=0,col=0;k<equ&&col<var;k++,col++)
    {
        max_r=k;
        for(int i=k+1;i<equ;i++) //找到第col列最大系数行 max_row
            if(abs(a[i][col])>abs(a[max_r][col]))
            max_r=i;
        if(a[max_r][col]==0)  //如果该列系数为0 则枚举的当前行数不变
        {
            k--;continue;
        }
        if(max_r!=k)  //如果最大系数行不是当前行 则交换这两行
            for(int j=col;j<=var;j++)
            swap(a[k][j],a[max_r][j]);
        for(int i=k+1;i<equ;i++)  //对于k行以下的行
        {
            if(a[i][col]!=0)
            {
                int LCM=lcm(abs(a[i][col]),abs(a[k][col]));
                int ta=LCM/abs(a[i][col]);
                int tb=LCM/abs(a[k][col]);
                if(a[i][col]*a[k][col]<0)tb=-tb;
                for(int j=col;j<=var;j++)
                    a[i][j]=meow(a[i][j]*ta-a[k][j]*tb); //用最小公倍数消去当前列的系数
            }
        }
    }

//    for(int i=0;i<equ;i++)
//        for(int j=0;j<=col;j++)
//        printf("%2d%c",a[i][j],j==col?'\n':' ');
    for(int i=k;i<equ;i++) //有全零项和不为0
        if(a[i][col]!=0)return -1;
    if(k<var) return var-k;
    for(int i=var-1;i>=0;i--)
    {
        int tmp=a[i][var];
        for(int j=i+1;j<var;j++)
        {
            if(a[i][j]!=0)
            {
                tmp=meow(tmp-a[i][j]*x[j]);
            }
        }
        x[i]=(tmp*inv(a[i][i],mod))%mod;
    }
//    for(int i=0;i<col;i++)
//        printf("%2d ",x[i]);printf("\n");
    return 0;
}

int cnt=0;
inline int getid(int x,int y)
{
    if(x>y)swap(x,y);
    if(id[x][y]!=-1) return id[x][y];
    return id[x][y]=cnt++;
}
int tot[510];
int f[201][201];
int main()
{
  //  freopen("in.txt","r",stdin);
    int n,st,ed,m;
    scanf("%d%d%d%d",&n,&st,&ed,&m);

    memset(id,0xff,sizeof id);
    for(int i=0;i<m;i++)
    {
        int k;
        scanf("%d%d",tot+i,&k);
        int x,y=0;
        for(int j=0;j<k;j++)
        {
            x=y;
            scanf("%d",&y);
            if(j)
            {
                int idx=getid(x,y);
//                if(x==y) while(1);
                a[i][idx]++;
                if(a[i][idx]>=mod)a[i][idx]-=mod;
            }
        }
    }
    for(int i=0;i<m;i++)
    {
        a[i][cnt]=tot[i];
    }
//    for(int i=0;i<m;i++)
//        for(int j=0;j<=cnt;j++)
//        printf("%d%c",a[i][j],j==cnt?'\n':' ');
    int res=gauss(m,cnt);
//    printf("%d\n",res);
    if(res==-1)while(1);
    else if(res!=0) f[300][300]=1;
//    printf("res:%d\n",res);
//    for(int i=0;i<cnt;i++)
//        printf("%d ",x[i]);printf("%d\n");
    memset(f,0x3f,sizeof f);
    for(int i=1;i<=n;i++)
        f[i][i]=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
    {
        if(id[i][j]==-1)continue;
//        printf("from %d  to %d %d\n",xx,y,x[id[i]]);
        f[i][j]=f[j][i]=x[id[i][j]];
    }
//    for(int i=1;i<=n;i++,puts(""))
//        for(int j=1;j<=n;j++)
//        printf("%d ",f[i][j]);
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
    {
        f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
    }
    printf("%d\n",f[st][ed]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/polya/p/9711042.html