P1211 街道赛跑

  又是一下午的杠题,累啊~~~

  这道题第一问很简单,只需去掉一个点,判断能不能到达终点就行了;

  第二问其实仔细想想也不难,就是判断去掉一个点后是否形成两个图;首先要知道是建立在第一问的基础上的;在加边的同时预处理一个e2的双向图,分别列举第一问的点,将从0到这个点所经过的点做标记;再将这点到终点遍历一遍,看是否遇到已标记过的点就行了。

  一个160行的代码,自己看吧...

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 5e5 + 100;
inline
int read() { int x = 0,ff = 1;char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') ff = -1; ch = getchar(); } while(isdigit(ch)) { x = (x<<1) + (x<<3) + (ch ^ 48); ch = getchar(); } return x * ff; } inline void write(int x) { if(x < 0) putchar('-'),x = -x; if(x > 9) write(x / 10); putchar(x % 10 + '0'); } struct node { int y,next; }e[MAXN],e2[MAXN << 1]; int a,tot = 0,head,tail,lin[MAXN]; int tot2 = 0,lin2[MAXN],vis2[MAXN]; int q[MAXN],vis[MAXN],dis[MAXN]; int f[MAXN],top = 0,F[MAXN],tom = 0; void add(int xx,int yy) { e[++tot].y = yy; e[tot].next = lin[xx]; lin[xx] = tot; } void add2(int xx,int yy) { e2[++tot2].y = yy; e2[tot2].next = lin2[xx]; lin2[xx] = tot2; } void Init() { int flag = 0; for(int i = 0;;++i) { int x; for(;;) { x = read(); if(x == -2) break; if(x == -1) { flag = 1; break; } add(i,x); add2(i,x); add2(x,i); } if(flag == 1) { a = i - 1; break; } } } void check(int m) { memset(vis,false,sizeof(vis)); vis[0] = true; vis[m] = true; head = 1,tail = 1; q[1] = 0; for(head = 1;head <= tail;++head) { int x = q[head]; for(int i = lin[x],y;i;i = e[i].next) { if(!vis[y = e[i].y]) { vis[y] = true; q[++tail] = y; } } } } bool check2(int m) { memset(vis,false,sizeof(vis)); memset(vis2,false,sizeof(vis2)); vis[0] = true; vis[m] = true; head = 1,tail = 1; q[1] = 0; for(head = 1;head <= tail;++head) { int x = q[head]; for(int i = lin2[x],y;i;i = e2[i].next) { if(!vis[y = e2[i].y]) { vis[y] = true; q[++tail] = y; } } } head = 1,tail = 1; q[1] = m; vis2[m] = true; vis[m] = false; for(head = 1;head <= tail;++head) { int x = q[head]; for(int i = lin[x],y;i;i = e[i].next) { if(vis[y = e[i].y]) return false; if(!vis2[y]) { vis2[y] = true; q[++tail] = y; } } } return true; } int main() { Init(); for(int i = 1;i < a;++i) { check(i); if(!vis[a]) f[++top] = i; } write(top); putchar(' '); for(int i = 1;i <= top;++i) { write(f[i]); putchar(' '); } putchar(' '); for(int i = 1;i <= top;++i) { if(check2(f[i])) F[++tom] = f[i]; } write(tom); putchar(' '); for(int i = 1;i <= tom;++i) { write(F[i]); putchar(' '); } return 0; }

  

原文地址:https://www.cnblogs.com/AK-ls/p/10164738.html