zoukankan      html  css  js  c++  java
  • HNOI2015菜肴制作

    一开始,没想出来,先topsort判环,把impossible拿到手,然后划分联通块,对每个联通块跑一遍topsort,觉得可对了,然后被大样例教育明白了,知道自己的策略错在哪了。

    接着在纸上疯狂手模样例,不停地换topsort的顺序和贪心的方法,然后发现一种可行的解法。

    开大根堆,对反图跑topsort,然后倒序输出。

    这是一种贪心的策略,通过上述操作,我们可以使不但大,而且限制多的不优秀点在最后输出,而小而且限制少的在前输出,既不违反规则,字典序又最小。

    换另一种解释,题目要我们输出满足拓扑序的最小字典序,是两个可能矛盾的量,他们之间可能存在冲突,那我们就倒着来,找满足拓扑逆序的最大字典序,这两个量都可以否定一个数字出现在靠前位置,把它们先找出来,然后倒着输出,就可以了。

    其实上述过程只用一个topsort就搞定了,但是博主略懒,以前的那个top判环没删,就直接用了,导致时间略长。大家还是自己去打打吧,就当复习topsort了。

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    using namespace std;
    int read(){
        int sum=0,f=1;char x=getchar();
        while(x<'0'||x>'9'){
            if(x=='-') f=-1;
            x=getchar();
        }while(x>='0'&&x<='9'){
            sum=sum*10+x-'0';
            x=getchar();
        }return sum*f;
    }
    int T,n,m,du[100500],pos[100500],ans[100500],size[100500],du1[100500],cnt;
    vector<int>edge[100500];
    vector<int>lcc[100500];
    vector<int>e[100500];
    bool v[100500];
    map<pair<int,int>,bool>mp[5];
    bool check(){
        bool vis[100500];
        memset(vis,0,sizeof(vis));
        queue<int>tops;
        while(!tops.empty()) 
            tops.pop();
        for(int i=1;i<=n;i++)
            if(du[i]==0){
                tops.push(i);
                vis[i]=1;
        //        cout<<i<<" ";
            }
        while(!tops.empty()){
            int x=tops.front();
            tops.pop();
            for(int i=0;i<edge[x].size();i++){
                int y=edge[x][i];
                du[y]--;
                if(du[y]==0){
                    tops.push(y);
                    vis[y]=1;
                //    cout<<y<<" ";
                }
            }
        }//cout<<endl;
    /*    for(int i=1;i<=n;i++)
            cout<<vis[i]<<" ";*/
        for(int i=1;i<=n;i++)
            if(!vis[i]) return 1;
        return 0;
    }
    void topsort(){
        priority_queue<int>q;
        for(int i=1;i<=n;i++)
            if(du1[i]==0)
                q.push(i);
        while(!q.empty()){
            int x=q.top();q.pop();ans[++ans[0]]=x;
            for(int i=0;i<e[x].size();i++){
                int y=e[x][i];
                du1[y]--;
                if(du1[y]==0)
                    q.push(y);
            }
        }
    }
    int main(){
        /*freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);*/
        T=read();
        while(T--){
            n=read();m=read();
            memset(ans,0,sizeof(ans));
            memset(du,0,sizeof(du));
            memset(v,0,sizeof(v));
            memset(du1,0,sizeof(du1));
            memset(e,0,sizeof(e));
            for(int i=1;i<=n;i++) edge[i].clear();
            for(int i=1,x,y;i<=m;i++){
                x=read();y=read();
                if(mp[T][make_pair(x,y)]) continue;
                mp[T][make_pair(x,y)]=1;
                edge[x].push_back(y);
            //    e[x].push_back(y);
                e[y].push_back(x);
                du[y]++;
                du1[x]++;
            }
            if(check()){
                puts("Impossible!");
                continue;
            }
            topsort();
            for(int i=n;i>=1;i--)
                printf("%d ",ans[i]);
            putchar('
    ');
        }
        return 0;
    }
    略丑,勿看
  • 相关阅读:
    【iCore3 双核心板_ uC/OS-III】例程三:任务的挂起与恢复
    病例讨论-----鼻窦炎一例(联想的风)
    桂枝二越婢一治疗鼻窦炎(联想的风)
    半夏厚朴汤治疗双肺支气管炎(联想的风)
    茯苓饮治疗呕吐(联想的风)
    半夏泻心汤治疗腹泻一例(联想的风)
    己椒苈黄汤治水肿案(联想的风)
    苓甘五味姜辛汤(联想的风病案)
    黃芩汤(联想的风病案)
    九味羌活汤的理解---王幸福
  • 原文地址:https://www.cnblogs.com/Yu-shi/p/11172087.html
Copyright © 2011-2022 走看看