您的位置:首页 > 其它

uvalive 6528(DAG,递推,想法/bitset, 好题)

2017-02-09 19:55 295 查看
题目链接

Nlogonia is a queendom that consists of several cities located on a big mountain. The capital cityis Logville, located on the mountain peak. Logville has a huge lake with a perfectly round shape,appropriately
named “The Big O”. This is the only lake with drinkable water in the entire queendom,so it is used to supply all cities. Some cities in Nlogonia are connected with water pipes that allow thedistribution of the water. As there are no pumps, each pipe carries
water from a city to another cityat a lower altitude, using gravity.

Nlogonia’s water system has been a source of worries for the Queen, because since cities depend onother cities for their water supply, hot discussions occur about how much water a city is allowed to
use.A water supply path is a sequence of cities in decreasing order of altitude, starting in Logville and suchthat there is a pipe connecting each pair of consecutive cities in the sequence. Two cities have disjointwater supply if and only if there exist two
water supply paths, one supply path ending in each of thecities, such that Logville is the only city that is present in both paths. Notice that Logville itself hasdisjoint water supply with every other city.

The Queen considers disjoint water supply a nice property because it reduces dependency problemsand also avoids water outages to spread as quickly through Nlogonia. She therefore ordered a surveyto
assess the current state of water supply disjointness in the whole queendom. Being the cleverestadvisors in the Queen’s court, you have been summoned to help calculate the number of pairs of distinctcities that have disjoint water supply.

Input

The input file contains several test cases, each of them as described below.

The first line contains two integers C
(2 ≤
C ≤
1000) and
P (1
≤ P
≤ 105),
representing respectively

the number of cities and the number of water pipes in Nlogonia. Cities are identified with differentintegers from 1 to
C, in strictly decreasing order of altitude (no two cities have the same altitude);Logville is city 1. Each of the next
P lines describes a pipe with two integers
U and
V (1
≤ U < V
≤ C)indicating that the pipe connects city
U with city
V . You may assume that no two pipes connect thesame pair of cities, and that for each city in Nlogonia there is at least one water
supply path that endsin it.

Output

For each test case, output a line with an integer representing the number of pairs of distinct cities thathave disjoint water supply.

Sample Input

661213142526368 111213142534673637482656

Sample Output

1426 

题意

1~n城市海拔从高到低,现在给出一些边,方向是从高到低。两个城市disjoint 当且仅当有两条路径从1出发,分别到这两个城市,且只在1节点相交。输出disjoint的城市有几对。

题解

方法1:分三类点,1. 与1直接相连,2. 所有1来的路径都必定经过某一点,3. 从1过来的路径没有必定经过的点。

第1和第3类点x,令f[x]=x,第2类点,令f[x]=p,p是必定经过的点的f。

第1类的好判断,判断2,3类需要利用已经计算出来的f:

因为边只能是海拔高到低的,下标小的海拔高,因此所有与 i 相连的比 i 小的点j 和k(j≠kj≠k)中若存在f[j]!=f[k],就是第3类,否则是第2类,p就是f[j]。

这样 f 相同的就是同一组,同一组内的就是不disjoint的。用总对数减去每组内的对数就是答案了。

方法2:

这题也可以用bitset水过去,用g[u]代表u必定经过的点,那么g[u]就是所有与其相连的所有前驱i的g[i]的交集。

方法1:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=1000+100;
int head[maxn];
struct edge
{
int to,next;
}e[maxn*200]; //
int tol=0;
void add(int u,int v)
{
e[++tol].to=v,e[tol].next=head[u],head[u]=tol;
}
int f[maxn],num[maxn];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(f,0,sizeof(f));
memset(num,0,sizeof(num));
memset(head,0,sizeof(head));
tol=0;
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
add(v,u);
}
f[1]=1;
rep(u,2,n+1)
{
int ff=-1;
bool flag=true;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==1)
{
flag=false;
break;
}
if(ff==-1) ff=f[v];
else
{
if(ff!=f[v])
flag=false;
}
}
if(flag) f[u]=ff;
else f[u]=u;
}
rep(i,1,n+1) num[f[i]]++;
int ans=n*(n-1)/2;
rep(i,2,n+1)
{
ans-=num[i]*(num[i]-1)/2;
}
printf("%d\n",ans);
}
return 0;
}


方法2:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=1e3+100;
const int maxm=1e5+100;
bitset<maxn> g[maxn];
int head[maxn];
struct edge
{
int from,to,next;
}e[maxm]; //
int tol=0;
void add(int u,int v)
{
e[++tol].to=v,e[tol].next=head[u],head[u]=tol;
}

int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
tol=0;
memset(head,0,sizeof(head));
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
rep(i,1,n+1) g[i].set();
g[1].reset();
rep(u,1,n+1) //g[i]表示结点i一定经过的点
{
if(u>1) g[u].set(u);
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
g[v]&=g[u];
}
}
int ans=0;
rep(i,1,n+1)
rep(j,i+1,n+1)
{
g[0]=g[i]&g[j];
if(g[0].count()==0) ans++;
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: