TTTTTTTTTTTTTT CF 645D 点的优先级

题意:给你n个节点,m对优先级关系,a[i] b[i]代表a[i]的优先级比b[i]高,现在问你至少需要前多少对关系就能确定所有节点的优先级;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const double pi=acos(-1);
const int mod=100000000;
ll max(ll a,ll b)
{return a>b?a:b;};
int min(int a,int b)
{return a<b?a:b;};

vector<int> G[100005];
int deg[100005],mp[100005],a[100005],b[100005];
int main()
{
    int n,m,u,v;
    while(~scanf("%d %d",&n,&m))
    {
         for(int i=1;i<=n;i++) G[i].clear();
         MM(deg,0);
         for(int i=1;i<=m;i++)
        {
            scanf("%d %d",&a[i],&b[i]);
            G[b[i]].push_back(a[i]);
            deg[a[i]]++;
        }
        queue<int> q;
        for(int i=1;i<=n;i++) if(deg[i]==0) q.push(i);
        int flag=1;
        while(q.size())
        {
            if(q.size()>1)
            {
                flag=0;
                break;
            }
            int u=q.front();q.pop();
            for(int i=0;i<G[u].size();i++)
            {
                int v=G[u][i];
                deg[v]--;
                if(deg[v]==0) q.push(v);
                mp[v]=u;
            }
        }
        if(!flag) printf("-1\n");
        else {
             int cnt=0;
             for(int i=1;i<=m;i++)
                 {
                     if(mp[a[i]]==b[i])  cnt++;
                     if(cnt==n-1) {printf("%d\n",i);break;}
                 }
        }
    }
    return 0;
}

  分析:很好的一道题,题目要求的其实就是什么时候能够找到一条从优先级最低的到

最高的一条路径,那么刚开始优先级最低的肯定是入度为0的点,接下来次底的呢?显然把与

最低的点相邻的边都删除了之后,入度为0的点就是次低的,并且只能有一个(因为存在一条

上述路径),若有>1个入度位0的点则无解,因为不存在合法路径,找到路径之后再枚举输入的边就好(因为两个节点之间至多一条边)

posted @ 2016-04-12 09:38  快点说我帅  阅读(325)  评论(0编辑  收藏  举报