zoukankan      html  css  js  c++  java
  • loj 1168(Tarjan应用)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26882

    思路:一开始把题意理解错了,还以为是简单路径,然后仔细一看发现是一条路径,意思就是说从起点出发,把所有的点走一遍,于是就要考虑强连通分量,因为对于同一个强连通分量的点是相互可达的,于是我们可以先缩点,建新图,统计新图中顶点的入度与出度的关系,判断即可。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<climits>
      7 #include<algorithm>
      8 #include<stack>
      9 #include<map>
     10 #include<set>
     11 #include<vector>
     12 #include<queue>
     13 #include<list>
     14 using namespace std;
     15 #define MAXN 1111
     16 #define inf 1<<30
     17 #define INF 1LL<<60
     18 #define FILL(a,b) memset(a,b,sizeof(a))
     19 typedef long long ll;
     20 typedef unsigned long long llu;
     21 typedef pair<int,int>PP;
     22 template<class T> inline T Get_MIN(const T &a,const T &b){ return a < b ? a : b; }
     23 template<class T> inline T Get_MAX(const T &a,const T &b){ return a > b ? a : b; }
     24 template<class T> inline T ABS(const T &a){ return a < 0 ? -a : a; }
     25 
     26 int n,m,k;
     27 bool vis[MAXN];
     28 vector<vector<int> >g,num;
     29 map<int,int>ID;
     30 
     31 int low[MAXN],dfn[MAXN],color[MAXN];
     32 int scc_count,cnt;
     33 bool mark[MAXN];
     34 stack<int>S;
     35 
     36 void Tarjan(int u)
     37 {
     38     low[u]=dfn[u]=++cnt;
     39     mark[u]=true;
     40     S.push(u);
     41     for(int i=0;i<g[u].size();i++){
     42         int v=g[u][i];
     43         if(dfn[v]==0){
     44             Tarjan(v);
     45             low[u]=Get_MIN(low[u],low[v]);
     46         }else if(mark[v]){
     47             low[u]=Get_MIN(low[u],dfn[v]);
     48         }
     49     }
     50     if(low[u]==dfn[u]){
     51         scc_count++;
     52         int v;
     53         do{
     54             v=S.top();
     55             S.pop();
     56             mark[v]=false;
     57             color[v]=scc_count;
     58         }while(u!=v);
     59     }
     60 }
     61 
     62 int In_degree[MAXN],Out_degree[MAXN];
     63 void Build()
     64 {
     65     FILL(In_degree,0);
     66     FILL(Out_degree,0);
     67     for(int u=1;u<=m;u++){
     68         for(int i=0;i<g[u].size();i++){
     69             int v=g[u][i];
     70             if(color[u]!=color[v]){
     71                 In_degree[color[v]]++;
     72                 Out_degree[color[u]]++;
     73             }
     74         }
     75     }
     76 }
     77 
     78 
     79 
     80 int main()
     81 {
     82     int _case,u,v,t=1;
     83     scanf("%d",&_case);
     84     while(_case--){
     85         scanf("%d",&n);
     86         g.clear();
     87         g.resize(1010);
     88         num.clear();
     89         num.resize(1010);
     90         ID.clear();
     91         FILL(vis,false);
     92         m=0;
     93         for(int i=1;i<=n;i++){
     94             scanf("%d",&k);
     95             while(k--){
     96                 scanf("%d%d",&u,&v);
     97                 if(!vis[u])vis[u]=true,ID[u]=++m;
     98                 if(!vis[v])vis[v]=true,ID[v]=++m;
     99                 g[ID[u]].push_back(ID[v]);
    100             }
    101         }
    102         FILL(dfn,0);
    103         FILL(mark,false);
    104         scc_count=cnt=0;
    105         for(int i=1;i<=m;i++){
    106             if(dfn[i]==0)Tarjan(i);
    107         }
    108         printf("Case %d: ",t++);
    109         if(scc_count==1){
    110             puts("YES");
    111             continue;
    112         }
    113         Build();
    114         if(Out_degree[color[ID[0]]]==0||In_degree[color[ID[0]]]!=0){
    115             puts("NO");
    116             continue;
    117         }
    118         int cnt1,cnt2,cnt3;
    119         cnt1=cnt2=cnt3=0;
    120         for(int i=1;i<=scc_count;i++){
    121             if(In_degree[i]==0&&Out_degree[i]==1)cnt1++;
    122             else if(In_degree[i]==1&&Out_degree[i]==0)cnt2++;
    123             else if(In_degree[i]==1&&Out_degree[i]==1)cnt3++;
    124         }
    125         if(cnt1==1&&cnt2==1&&cnt1+cnt2+cnt3==scc_count){
    126             puts("YES");
    127         }else
    128             puts("NO");
    129     }
    130     return 0;
    131 }
    View Code
  • 相关阅读:
    产生唯一的临时文件mkstemp()
    Linux文档时间戳查看和修改——stat
    Linux下快速查找文件
    Crypt加密函数简介(C语言)
    产生随机数 random
    见微知著——从《新闻联播》挖掘价值资讯擒拿年度政策受益牛股
    Linux中link,unlink,close,fclose详解
    不用输液
    javaScript document对象详解
    javascript初步了解
  • 原文地址:https://www.cnblogs.com/wally/p/3350388.html
Copyright © 2011-2022 走看看