烦人的幻灯片——入度为1,栈,模仿拓扑排序

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 18:24   2829   0

题目:http://www.sqyoj.club/problem.php?id=1016

思路:如果数i坐标在某幻灯片X范围内,则建立双向边,并增加数i的入度。遍历所点数,将入度为1的点存入栈。

从栈中取出一个数,并将该数连接的字母染色,再将该字母连接的数字的入度都减1,如果数字的入度是1,则将数字入栈。反复进行,直到栈空。如果栈内存入的数字刚好是n个,则说明可行,否则输出“None”。

这个操作与求拓扑排序的入度为0法的算法完全类似。

AC代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,x,y,stack[105],rd[105];
int x1[105],x2[105],y1[105],y2[105];
int a[105];
int cns,cnt,sum;
int num,head[105];
bool vis[105];
struct Edge{
 int from,to,next;
};
Edge edge[215];
void join(int from,int to){
 ++num;
 edge[num].next=head[from];
 edge[num].from=from;
 edge[num].to=to;
 head[from]=num;
}
int main(){
 memset(head,-1,sizeof(head));
 cin>>n;
 for(int i=1;i<=n;i++)
  cin>>x1[i+'A'-1]>>x2[i+'A'-1]>>y1[i+'A'-1]>>y2[i+'A'-1];
 for(int i=1;i<=n;i++){
  cin>>x>>y;
  for(int j=1;j<=n;j++)
   if( x>x1[j+'A'-1] && x<x2[j+'A'-1]
   && y>y1[j+'A'-1] && y<y2[j+'A'-1] ){
    join(j+'A'-1,i);
    join(i,j+'A'-1);
    rd[i]++;
   }
    
 }
 for(int i=1;i<=n;i++)
  if(rd[i]==1)stack[++cns]=i; 
 while(cns){
  int nd=stack[cns];
  cns--;
  cnt++;
  int from,to;
  for(int i=head[nd];i!=-1;i=edge[i].next){
   from=edge[i].to;
   if(!vis[from]){
    vis[from]=1;
    a[from]=nd;
    break;
   }
  }
  for(int i=head[from];i!=-1;i=edge[i].next){
   to=edge[i].to;
   rd[to]--;
   if(rd[to]==1){
    cns++;
    stack[cns]=to;
   }  
  }
 }
 if(cnt==n)
  for(int i=1;i<=n;i++)
   printf("%c %d\n",i+'A'-1,a[i+'A'-1]);
 else cout<<"None\n";
 return 0;
}

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP