zoukankan      html  css  js  c++  java
  • [SDOI2010] 所驼门王的宝藏 [建图+tarjan缩点+DAG dp]

    题面传送门:

    传送门

    思路:

    看完题建模,容易得出是求单向图最长路径的问题

    那么把这张图缩强联通分量,再在DAG上面DP即可

    然而

    这道题的建图实际上才是真正的考点

    如果对于每一个点都直接连边到它所有的后继节点,那么可以被卡掉(1e5个点在同一行上)

    考虑改变思路,运用网络流建图中的一个常用技巧:把横边和竖边映射成点,再从每个点向所在横坐标、纵坐标代表的点连边即可

    这样会有2e6+1e5个点,但是tarjan算法效率O(n),完全无压力

    自由(和谐)门的话,目前还没有比较好的方法解决

    上网看了一圈题解,也都是排序或者map的

    这里就用map

    //为什么自由(和谐)门会是违规的啊......

    Code:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<map>
      6 #include<vector>
      7 #define mp make_pair
      8 #pragma comment(linker, "/STACK:202400000,202400000")
      9 using namespace std;
     10 const int dx[9]={0,1,1,1,0,0,-1,-1,-1},dy[9]={0,-1,0,1,-1,1,-1,0,1};
     11 inline int read(){
     12     int re=0,flag=1;char ch=getchar();
     13     while(ch>'9'||ch<'0'){
     14         if(ch=='-') flag=-1;
     15         ch=getchar();
     16     }
     17     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
     18     return re*flag;
     19 }
     20 int n,r,c,first[2100010],First[2100010],cnt=0,Cnt=0;
     21 int dfn[2100010],low[2100010],num=0;
     22 int s[2100010]={0},top=0;
     23 int belong[2100010],tot=0,dp[2100010],siz[2100010],in[2100010];
     24 bool vis[2100010];
     25 int x[100010],y[100010];
     26 struct edge{
     27     int from,to,next;
     28 }a[2000010];
     29 struct Edge{
     30     int to,next;
     31 }e[2000010];
     32 inline void add(int u,int v){
     33 //    cout<<"add "<<u<<ends<<v<<endl;
     34     a[++cnt]=(edge){u,v,first[u]};first[u]=cnt;
     35 }
     36 inline void Add(int u,int v){
     37     e[++Cnt]=(Edge){v,First[u]};First[u]=Cnt;
     38 }
     39 map<pair<int,int>,int>m;
     40 void tarjan(int u){
     41 //    cout<<"tarjan "<<u<<endl;
     42     int i,v;vis[u]=1;
     43     dfn[u]=low[u]=++num;
     44     s[++top]=u;
     45     for(i=first[u];~i;i=a[i].next){
     46         v=a[i].to;
     47         if(belong[v]) continue;
     48         if(!dfn[v]){
     49             tarjan(v);
     50             low[u]=min(low[u],low[v]);
     51         }
     52         else low[u]=min(low[u],dfn[v]);
     53     }
     54     if(low[u]==dfn[u]){
     55         ++tot;
     56         while(s[top]!=u){
     57             belong[s[top]]=tot;
     58             if(s[top]>r+c) siz[tot]++;
     59 //            qlt[tot].push_back(s[top]);
     60             s[top--]=0;
     61         }
     62         belong[s[top]]=tot;
     63         if(s[top]>r+c) siz[tot]++;
     64 //        qlt[tot].push_back(s[top]);
     65         s[top--]=0;
     66     }
     67 }
     68 int q[2100010],head=0,tail=0;
     69 int main(){
     70 //    freopen("sdoi10sotomon.in","r",stdin);
     71 //    freopen("sdoi10sotomon.out","w",stdout);
     72     memset(first,-1,sizeof(first));
     73     memset(First,-1,sizeof(First));
     74     int i,t1,t2,t3,t4,t5,j,u,v,ans=0;
     75     map<pair<int,int>,int>::iterator tmp;
     76     memset(first,-1,sizeof(first));
     77     n=read();r=read();c=read();
     78     for(i=1;i<=n;i++){
     79         t1=read();t2=read();t3=read();
     80         x[i]=t1;y[i]=t2;
     81         m[mp(t1,t2)]=i;
     82         add(t1,r+c+i);add(t2+r,i+r+c);
     83         if(t3==1) add(r+c+i,t1);
     84         if(t3==2) add(r+c+i,r+t2);
     85         if(t3==3) vis[i]=1;
     86     }
     87     for(i=1;i<=n;i++){
     88         if(!vis[i]) continue;
     89         t1=x[i];t2=y[i];
     90         for(j=1;j<=8;j++){
     91             t3=t1+dx[j];t4=t2+dy[j];
     92             tmp=m.find(mp(t3,t4));
     93             if(tmp==m.end()) continue;
     94             add(r+c+i,r+c+tmp->second);
     95         }
     96     }
     97     memset(vis,0,sizeof(vis));
     98     for(i=1;i<=r+c+n;i++) if(!vis[i]) tarjan(i);
     99 //    cout<<"end of tarjan"<<endl;
    100 //    for(i=1;i<=r+c+n;i++) cout<<belong[i]<<ends;
    101 //    for(i=1;i<=tot;i++){
    102 //        for(j=0;j<qlt[i].size();j++) cout<<qlt[i][j]<<ends;
    103 //        cout<<endl;
    104 //    }
    105     for(i=1;i<=cnt;i++){
    106         if(!belong[a[i].from]||!belong[a[i].to]) continue;
    107         if(belong[a[i].from]==belong[a[i].to]) continue;
    108         Add(belong[a[i].from],belong[a[i].to]);in[belong[a[i].to]]++;
    109     }
    110 //    cout<<"end of Add
    ";
    111     for(i=1;i<=tot;i++) if(!in[i]) q[tail++]=i,dp[i]=siz[i];
    112     while(head<tail){
    113         u=q[head++];
    114         for(i=First[u];~i;i=e[i].next){
    115             v=e[i].to;
    116             dp[v]=max(dp[v],dp[u]+siz[v]);in[v]--;
    117             if(!in[v]) q[tail++]=v;
    118         }
    119     }
    120     for(i=1;i<=tot;i++) ans=max(ans,dp[i]);
    121     printf("%d",ans);
    122 }
  • 相关阅读:
    json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
    Java中时间与时间戳的转换
    python爬取网页数据
    selenium爬取网页内容知识点总结(代码均亲测可用)
    【LeetCode 5】 最长回文子串
    【LeetCode 4】寻找两个有序数组的中位数
    【LeetCode 3】无重复字符的最长子串
    【LeetCode 1】两数之和
    【LeetCode 2】两数相加
    【3-4】数字三角形问题
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8446523.html
Copyright © 2011-2022 走看看