POJ--2553 图的底部

简介: POJ--2553 图的底部

题目描述


20210313224247268.png

输入样例


3 3
1 3 2 3 3 1
2 1
1 2
0


输出样例


1 3
2


思路

G中任意两个点都可到达,则G是图的一个强连通分量.sink点就是强连通分量中的点.题目要求是输出sink点.

所以我们应该先通过Tarjan算法找到强连通分量,然后缩点,统计每个(缩点)的出度,最后缩点出度为1的那些点就是我们要求的sink点.


20210313224823938.png

20210313224845405.png

参考代码

#include<iostream>
#include<stack>
#include<string.h>
using namespace std;
const int maxn = 5000+10;
int n,m;
int head[maxn],num,ins[maxn],low[maxn],dfn[maxn],cnt,belong[maxn],id,degree[maxn];//ins:标记是否在 stack中 
stack<int> s;
struct Edge{
  int to,next; 
}e[maxn*maxn]; 
void add(int u,int v){
  e[++num].next = head[u];
  e[num].to = v;
  head[u] = num;
}
void tarjan(int u){
  low[u] = dfn[u] = ++cnt;
  ins[u] = 1;
  s.push(u);
  for(int i = head[u]; i ; i = e[i].next){
    int v = e[i].to;
    if(!dfn[v]){
      tarjan(v);
      low[u] = min(low[u],low[v]);
    }else if(ins[v]){
      low[u] = min(low[u],low[v]);
    }
  }
  if(low[u]==dfn[u]){//缩点 
    int v;
    do{
      v = s.top();
      s.pop();
      belong[v] = id;
      ins[v] = 0; 
    }while(u!=v);
    id++;
  }
}
void init()
{
  memset(head,0,sizeof(head));
  memset(ins,0,sizeof(ins));
  memset(low,0,sizeof(low));
  memset(dfn,0,sizeof(dfn));
  memset(belong,0,sizeof(belong));
  memset(degree,0,sizeof(degree));
  num = cnt =0;
  id  = 1;
}
void solveDegree(){//求出度
  for(int u = 1; u <= n; u++){
    for(int i = head[u]; i; i = e[i].next){
      int v = e[i].to;
      if(belong[u]!=belong[v]){//如果u和v的连通分量号不同 
        degree[belong[u]]++;//u节点所在的连通分量号的出度++ 
      }
    }
  }
}
void print(){//输出  
  int flag = 1; 
  for(int i = 1;i <= n; i++){
    if(!degree[belong[i]]){//如果出度为0则说明是连通分量
      if(flag){//第一个数据前没有空格 
        flag = 0;
      }else{
        cout<<" ";
      }
      cout<<i;
    }
  }
  cout<<endl; 
} 
int main(){
  int u,v;
  while(cin>>n&&n){
    cin>>m;
    while(m--){
      cin>>u>>v;
      add(u,v);
    }
    for(int i = 1; i <= n; i++){
      if(!dfn[i]){
        tarjan(i);
      }
    }
    solveDegree();
    print();
    init();
  }
  return 0;
}
相关文章
UG02界面定制---左上角点击文件新建,选择做靠边栏倒数第三个Content是,选择它的基本功能,UG不想要工具栏,可以拖动删除它,最上方工具栏有定制,Ctrl + 1,文字在定制的文本,右键加命令
UG02界面定制---左上角点击文件新建,选择做靠边栏倒数第三个Content是,选择它的基本功能,UG不想要工具栏,可以拖动删除它,最上方工具栏有定制,Ctrl + 1,文字在定制的文本,右键加命令
UG01---NX10头部是标题栏 ,界面认识,进入全屏点击右下角,继续点击就退出了
UG01---NX10头部是标题栏 ,界面认识,进入全屏点击右下角,继续点击就退出了
|
4月前
|
机器学习/深度学习 算法 C++
【算法 | 实验6-1】n*n的网格,从左上角开始到右下角结束遍历所有的方块仅一次,总共有多少种不同的遍历路径
前言 思路介绍中省略了关于如何进行回溯搜索的细节,而主要讨论回溯中所使用的剪枝策略。
107 0
鼠标放上边框变虚转圈效果demo效果示例(整理)
鼠标放上边框变虚转圈效果demo效果示例(整理)
向上滑动导航固定头部demo效果图示例(整理)
向上滑动导航固定头部demo效果图示例(整理)
|
数据可视化 Go
R-forestplot包| HR结果绘制森林图
R-forestplot包| HR结果绘制森林图
281 0
leetcode 513 找左下角的值
leetcode 513 找左下角的值
51 0
leetcode 513 找左下角的值
AcWing 750. 数组的下方区域
AcWing 750. 数组的下方区域
44 0
AcWing 750. 数组的下方区域
AcWing 749. 数组的上方区域
AcWing 749. 数组的上方区域
54 0
AcWing 749. 数组的上方区域
ZCMU - 2065: 打印十字图
ZCMU - 2065: 打印十字图
85 0
ZCMU - 2065: 打印十字图