zoukankan      html  css  js  c++  java
  • bzoj1194

    O(S²)枚举2个诅咒机, 然后O(n²)BFS去判断. 构成一个有向图, tarjan缩点, 然后就是求DAG的最长路——题解来自lsj

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<ctime>
      5 #include<cmath>
      6 #include<iostream>
      7 #include<algorithm>
      8 #include<queue>
      9 #include<stack>
     10 #include<set>
     11 #define clr(a,x) memset(a,x,sizeof(a))
     12 #define rep(i,l,r) for(int i=(l);i<(r);i++)
     13 using namespace std;
     14 typedef long long ll;
     15 typedef pair<int,int> pii;
     16 #define mkp(a,b) make_pair(a,b)
     17 int read(){
     18     int ans=0,f=1;
     19     char c=getchar();
     20     while(!isdigit(c)){
     21         if(c=='-') f=-1;
     22         c=getchar();
     23     }
     24     while(isdigit(c)){
     25         ans=ans*10+c-'0';
     26         c=getchar();
     27     }
     28     return ans*f;
     29 }
     30 const int maxs=59,maxn=59,maxm=59;
     31 struct edge{
     32     int v;
     33     edge*next;
     34 }e[maxn*maxn],*fir[maxn],*pt=e,E[maxn*maxn],*Fir[maxn],*Pt=E;
     35 void addedge(int u,int v){
     36     pt->v=v;pt->next=fir[u];
     37     fir[u]=pt++;
     38 }
     39 void Addedge(int u,int v){
     40     Pt->v=v;Pt->next=Fir[u];
     41     Fir[u]=Pt++;
     42 }
     43 int s,n[maxs],m[maxs],v[maxs][maxn][2];
     44 bool vis[maxn][maxn],f[maxs][maxn];
     45 bool bfs(int x,int y){
     46     queue<pii>Q;Q.push(mkp(0,0));
     47     clr(vis,0);
     48     while(!Q.empty()){
     49         int a=Q.front().first,b=Q.front().second;Q.pop();
     50         rep(i,0,2){
     51             int U=v[x][a][i],V=v[y][b][i];
     52             if(vis[U][V]) continue;
     53             if(f[x][U]&&!f[y][V]) return 0;
     54             Q.push(mkp(U,V));vis[U][V]=1;
     55         }
     56     }
     57     return 1;
     58 }
     59 int ans,dfstime,scccnt,size[maxn],pre[maxn],low[maxn],scc[maxn];
     60 stack<int>S;
     61 void dfs(int x){
     62     pre[x]=low[x]=++dfstime;S.push(x);
     63     for(edge*e=fir[x];e;e=e->next){
     64         if(!pre[e->v]){
     65             dfs(e->v);
     66             low[x]=min(low[x],low[e->v]);
     67         }else if(!scc[e->v]) low[x]=min(low[x],pre[e->v]);
     68     }
     69     if(pre[x]==low[x]){
     70         int t=-1;++scccnt;
     71         while(t!=x){
     72             t=S.top();S.pop();
     73             scc[t]=scccnt;size[scccnt]++;
     74         }
     75     }
     76 }
     77 void tarjan(){
     78     rep(i,0,s) if(!scc[i]) dfs(i);
     79     clr(vis,0);
     80     rep(i,0,s){
     81         for(edge*e=fir[i];e;e=e->next){
     82             if(scc[i]!=scc[e->v]&&!vis[scc[i]][scc[e->v]]){
     83                 vis[scc[i]][scc[e->v]]=1;Addedge(scc[i],scc[e->v]);
     84             }
     85         }
     86     }
     87 }
     88 bool in[maxn];
     89 int w[maxn];
     90 void dp(int x){
     91     if(w[x]) return;
     92     for(edge*e=Fir[x];e;e=e->next){
     93         dp(e->v);w[x]=max(w[x],w[e->v]);
     94     }
     95     w[x]+=size[x];
     96 }
     97 void solve(){
     98     tarjan();
     99     rep(i,1,scccnt+1){
    100         for(edge*e=Fir[i];e;e=e->next) in[e->v]=1;
    101     }
    102     rep(i,1,scccnt+1) if(!in[i]) dp(i);
    103     rep(i,1,scccnt+1) ans=max(ans,w[i]);
    104     printf("%d
    ",ans);
    105 }
    106 int main(){
    107     s=read();
    108     rep(i,0,s){
    109         n[i]=read();m[i]=read();
    110         rep(j,1,m[i]+1){
    111             int t=read();
    112             f[i][t]=1;
    113         }
    114         rep(j,0,n[i]){
    115             v[i][j][0]=read();v[i][j][1]=read();
    116         }
    117     }
    118     rep(i,0,s){
    119         rep(j,0,s) if(i!=j&&bfs(i,j)) addedge(i,j);
    120     }
    121     solve();
    122     return 0;
    123 }
    View Code

    1194: [HNOI2006]潘多拉的盒子

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 255  Solved: 133
    [Submit][Status][Discuss]

    Description

     

    Input

    第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50)。文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语机S-1的顺序描述。每一块的格式如下。 一块的第一行有两个正整数n,m。分别表示该咒语机中元件的个数、咒语源输出元的个数(1≤m≤n≤50)。 接下来一行有m个数,表示m个咒语源输出元的标号(都在0到n-1之间)。接下来有n行,每一行两个数。第i行(0≤i≤n-1)的两个数表示pi,0和pi,1(当然,都在0到n-1之间)。

    Output

    第一行有一个正整数t,表示最长升级序列的长度。

    Sample Input

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

    Sample Output

    3

    HINT

     

    Source

     
    [Submit][Status][Discuss]
  • 相关阅读:
    人机博弈,吃子棋游戏(一)基本介绍
    cesm下载备注
    mysql数据库批量高速插入
    持续学习
    顺序表的功能实现
    Broccoli &amp; Babel使用演示样例
    rk3188调试记录
    Operation not allowed on a unidirectional dataset错误?
    dbExpress操作中用TDBGrid显示数据
    dbexpress连接mysql提示Operation not allowed on a unidirectional dataset
  • 原文地址:https://www.cnblogs.com/chensiang/p/4992883.html
Copyright © 2011-2022 走看看