bzoj2788 festival 差分约束

填坑中……链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2788

题意:

有$n$个正整数$X1,X2,...,Xn$,再给出$m1+m2$个限制条件,限制分为两类:
1. 给出$a,b(1<=a,b<=n)$,要求满足$Xa + 1 = Xb$
2. 给出$c,d (1<=c,d<=n)$,要求满足$Xc <= Xd$
在满足所有限制的条件下,求集合${Xi}$大小的最大值。

首先看情况我们也知道是差分约束……

但是这个差分约束有些不一样在于这个东西会出环……所以我们要得出强连通分量……

得出来之后对于每个$SCC$分别考虑就行了……

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 const int maxn=605,maxm=200005;
  7 const int inf=0x3f3f3f3f;
  8 int n,m1,m2,cnt,tot,scnt;
  9 int head[maxn],MAP[maxn][maxn];
 10 int dfn[maxn],low[maxn],belong[maxn];
 11 struct node
 12 {
 13     int from,to,dis,next;
 14 }edge[maxm];
 15 void addedge(int u,int v,int w)
 16 {
 17     edge[++tot]=(node){u,v,w,head[u]};head[u]=tot;
 18 }
 19 #include<stack>
 20 stack<int>s;
 21 void tarjan(int root)
 22 {
 23     dfn[root]=low[root]=++cnt;s.push(root);
 24     for(int i=head[root];i;i=edge[i].next)
 25     {
 26         int v=edge[i].to;
 27         if(!dfn[v])
 28         {
 29             tarjan(v);
 30             low[root]=min(low[root],low[v]);
 31         }
 32         else if(!belong[v])low[root]=min(low[root],dfn[v]);
 33     }
 34     if(low[root]==dfn[root])
 35     {
 36         scnt++;int k;
 37         do
 38         {
 39             k=s.top();s.pop();
 40             belong[k]=scnt;
 41         }while(k!=root);
 42     }
 43 }
 44 int haha()
 45 {
 46     scanf("%d%d%d",&n,&m1,&m2);
 47     for(int i=1;i<=n;i++)
 48         for(int j=1;j<=n;j++)MAP[i][j]=-inf;
 49     for(int i=1;i<=n;i++)MAP[i][i]=0;
 50     for(int i=1;i<=m1;i++)
 51     {
 52         int x,y;scanf("%d%d",&x,&y);
 53         addedge(x,y,1),addedge(y,x,-1);
 54         MAP[x][y]=max(MAP[x][y],1);MAP[y][x]=max(MAP[y][x],-1);
 55     }
 56     for(int i=1;i<=m2;i++)
 57     {
 58         int x,y;scanf("%d%d",&x,&y);
 59         addedge(x,y,0);MAP[x][y]=max(MAP[x][y],0);
 60     }
 61     for(int i=1;i<=n;i++)
 62         if(!dfn[i])tarjan(i);
 63     int ans=0;
 64     for(int b=1;b<=scnt;b++)
 65     {
 66         int ret=0;
 67         for(int k=1;k<=n;k++)
 68         {
 69             if(belong[k]!=b)continue;
 70             for(int i=1;i<=n;i++)
 71             {
 72                 if(belong[i]!=b)continue;
 73                 if(MAP[i][k]==-inf)continue;
 74                 for(int j=1;j<=n;j++)
 75                 {
 76                     if(belong[j]!=b)continue;
 77                     if(MAP[k][j]==-inf)continue;
 78                     MAP[i][j]=max(MAP[i][j],MAP[i][k]+MAP[k][j]);
 79                 }
 80             }
 81         }
 82         for(int i=1;i<=n;i++)
 83         {
 84             if(belong[i]!=b)continue;
 85             for(int j=1;j<=n;j++)
 86             {
 87                 if(belong[j]!=b)continue;
 88                 ret=max(ret,abs(MAP[i][j]));
 89             }
 90         }
 91         ans+=ret+1;
 92     }
 93     for(int i=1;i<=n;i++)
 94         if(MAP[i][i])
 95         {
 96             puts("NIE");
 97             return 0;
 98         }
 99     printf("%d\n",ans);
100 }
101 int sb=haha();
102 int main(){;}
bzoj2788

 

转载于:https://www.cnblogs.com/Loser-of-Life/p/7351585.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值