设为首页 加入收藏

TOP

ZOJ 3811 Untrusted Patrol 并查集
2015-07-20 17:44:20 来源: 作者: 【 】 浏览:1
Tags:ZOJ 3811 Untrusted Patrol 查集

题目链接:点击打开链接

题意:

给定n个点m条边的无向图,k个触发器。

下面k个数表示触发器安装在哪几个点。

下面m行给出边

最后有l个信号,

给出信号发出的触发器的顺序。

每个触发器只会发出一次信号,且一个点只有一个触发器。

有一个人在遍历图。

每经过一个点,那个点的触发器就会发出信号,问是否存在一种走法使得这个人遍历了所有点且触发器发出的信号顺序和给出的一样。

思路:

先把无触发器的点放到图里。

然后根据触发器的信号顺序把点依次加入图中,加入时只添加(与无触发器点相连的边)

然后判断这个点能否与之前的图连通。bfs+并查集判断。

==其实并查集就够了,写的时候有脑洞,bfs就冒出来了

#include
  
   
#include
   
     #include
    
      #include
     
       #include
      
        #include 
       
         using namespace std; #define ll int typedef pair
        
          pii; #define M 400010 #define N 200010 int f[N]; int find(int x){return x==f[x]?x:f[x] = find(f[x]);} void Union(int x,int y){ int fx = find(x), fy = find(y); if(fx==fy)return ; if(fx>fy)swap(fx,fy); f[fx] = fy; } struct Edge{ int from, to, nex; }edge[M<<1]; int head[N], edgenum; void init(){memset(head, -1, sizeof head); edgenum = 0;} void add(int u, int v){ Edge E = {u, v, head[u]}; edge[edgenum] = E; head[u] = edgenum++; } int n, m, k, l; int is[N], vis[N]; vector
         
          G, E[N]; void ADD(int x){ for(int i = 0; i < E[x].size(); i++){ if(is[E[x][i]] == 0) add(x, E[x][i]); } is[x] = 0; } void bfs(int x){ queue
          
           q; q.push(x); vis[x] = 1; while(!q.empty()){ int u = q.front(); q.pop(); for(int i = head[u]; ~i; i = edge[i].nex) { int v = edge[i].to; Union(v, x); if(vis[v])continue; vis[v] = 1; q.push(v); } } } bool solve(){ scanf("%d %d %d",&n,&m, &k); init(); int i, j, u, v; for(i = 1; i <= n; i++) { vis[i] = is[i] = 0; E[i].clear(); } for(i = 1; i <= k; i++) { scanf("%d",&j); is[j] = 1; } while(m--){ scanf("%d %d", &u, &v); E[u].push_back(v); E[v].push_back(u); } G.clear(); scanf("%d", &l); for(i = 1; i <= l; i++) { scanf("%d", &j); G.push_back(j); } //若触发器没有全响,就不行 if(k!=l)return false; //若没有触发器一定可以。 if(k == 0) return true; for(i = 1; i <= n; i++) { if(is[i] == 0) { for(j = 0; j < E[i].size(); j++) if(is[E[i][j]]==0) add(i, E[i][j]); } } for(i = 1; i <= n; i++) f[i] = i; for(i = 0; i < G.size(); i++) { u = G[i]; ADD(u); bfs(u); if(i-1>=0){ find(G[i]); find(G[i-1]); if(f[G[i]] != f[G[i-1]]) return false; } } for(i = 1; i <= n; i++) if(vis[i] == 0) return false; return true; } int main(){ int T; scanf("%d",&T); while(T--) solve() ? puts("Yes"):puts("No"); return 0; } /* 99 5 5 3 1 2 4 1 2 2 3 3 1 1 4 4 5 3 4 2 1 5 5 3 1 2 4 1 2 2 3 3 1 1 4 4 5 3 4 1 2 7 8 3 1 3 5 1 2 1 3 2 3 2 4 3 6 5 4 5 7 6 7 3 5 3 1 7 8 5 3 6 4 5 7 1 2 1 3 2 3 2 4 3 6 5 4 5 7 6 7 5 3 6 4 5 7 7 8 5 3 6 4 5 7 1 2 1 3 2 3 2 4 3 6 5 4 5 7 6 7 5 3 6 5 4 7 8 8 5 3 6 4 5 7 1 2 1 3 2 3 2 4 3 6 5 4 5 7 6 7 5 3 6 4 5 7 ans: N Y Y Y N N */ 
          
         
        
       
      
     
    
   
  


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇jpa的双向一对多和双向一对一关联.. 下一篇ZOJ 3814 Sawtooth Puzzle 状态压..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·常用meta整理 | 菜鸟 (2025-12-25 01:21:52)
·SQL HAVING 子句:深 (2025-12-25 01:21:47)
·SQL CREATE INDEX 语 (2025-12-25 01:21:45)
·Shell 传递参数 (2025-12-25 00:50:45)
·Linux echo 命令 - (2025-12-25 00:50:43)