洛谷P1347 排序

这个题看到很多人写Topo排序,其实这道题第一眼看更像是一个差分约束的裸题QWQ...


令dis[x]表示x的相对大小(1是最小,n是最大),显然,对于一个关系A<B,我们有dis[A]<dis[B],也就是dis[A]<=dis[B]-1,然后我们就可以建一条从B到A的权值为-1的有向边.


而我们最后要求的就是dis[x]的最小值,为了使它们的值都落在1~n之间,我们新建一个虚拟的点0,并令dis[0]=0且dis[x]>dis[0].


这样我们要求的就是dis[x]-dis[0]的最小值啦~\(≧▽≦)/~.


显然这可以转换为一个图论问题(也就是最长路),我比较喜欢用最短路,所以把它转化一下变成-(dis[0]-dis[x]).


dis[0]-dis[x]就是x到0的最短路,我们可以把它转变成一个单源最短路,就是建反向边,跑一个以0为起点的单源最短路就可以啦,最后记得取相反数哦

By 520Enterprise

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int n,m,dis[maxn],in[maxn],cnt[maxn],head[maxn],eps,tot,vis[maxn];
struct edge
{
    int to,next,quan;
}e[maxn];
deque<int>q;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
inline void write(int a)
{
    if(a<0)
    {
        char a='-',b='1';
        putchar(a);
        putchar(b);
    }
    else
    {
        if(a>=10)
            write(a/10);
        putchar(a%10+'0');
    }
}
void add(int to,int from,int quan)
{
    e[++tot]=(edge){to,head[from],quan};
    head[from]=tot;
}
int SPFA(int s)
{
//    memset(dis,0x3f,sizeof(dis));
    memset(cnt,0,sizeof(cnt));
    memset(vis,0,sizeof(vis));
    in[s]=1,q.push_front(s);
    in[0]=1,q.push_front(0);
    while(!q.empty())
    {
        int now=q.front();
        q.pop_front();
        in[now]=0;
//        cout<<"now "<<now<<' '<<dis[now]<<endl;
        for(int i=head[now];i;i=e[i].next)
        {
            int to=e[i].to;            
            if(dis[to]>dis[now]+e[i].quan)
            {
                dis[to]=dis[now]+e[i].quan;
                if(++cnt[to]>n)
                    return 0;
                if(!in[to])
                {
                    if(dis[to]<dis[q.front()]+eps||(2<=cnt[to]&&cnt[to]<=eps))
                        q.push_front(to);
                    else
                        q.push_back(to);
                    in[to]=1;
                }
            }
//            cout<<"to "<<to<<' '<<dis[to]<<endl;
        }
    }
    for(int i=1;i<=n;++i)
        vis[-dis[i]]=1;
    for(int i=1;i<=n;++i)
        if(!vis[i])
            return -1;
    return 1;
}
int main()
{
    memset(dis,0x3f,sizeof(dis));
    dis[0]=0;
    n=read(),m=read(),tot=0;        
    for(int i=1;i<=n;++i)
        add(i,0,-1);
    eps=sqrt(n);
    for(int i=1;i<=m;++i)
    {
        char ch1,ch2,ch3;
        cin>>ch1>>ch2>>ch3;
        add(ch3-'A'+1,ch1-'A'+1,-1);
        int flag=SPFA(ch1-'A'+1);
        if(!flag)
        {
            printf("Inconsistency found after %d relations.",i);
            return 0;
        }
        else if(flag>0)
        {
            printf("Sorted sequence determined after %d relations: ",i);
            for(int j=1;j<=n;++j)
                for(int k=1;k<=n;++k)
                    if(dis[k]==-j)
                    {
                        putchar('A'+k-1);
                        break;
                    }
            putchar('.');
            return 0;
        }
    }
    printf("Sorted sequence cannot be determined.");
    return 0;
}
posted @ 2019-12-11 21:53  520Enterprise  阅读(152)  评论(0编辑  收藏  举报