Real Magic
给一个无向图,问每个点能到达的点的数量。
直接并查集维护连通块点数。
#include <iostream>
#include <cstring>
#include <cmath>
#include <bitset>
#include <queue>
#include <vector>
#include <cstdio>
#include <set>
#include <stack>
#include <sstream>
#include <cstring>
#include <algorithm>
#include <map>
#define rep(i, a, b) for (long long i= a; i <= b; i++)
#define reps(i, a, b) for (long long i = a; i >= b; i--)
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/gcd(a,b)
#define ls(node) tree[node].ls
#define rs(node) tree[node].rs
#define val(node) tree[node].val
#define sum(node) tree[node].sum
#define lazy(node) tree[node].lazy
#define lazy1(node) tree[node].lazy1
#define lazy2(node) tree[node].lazy2
#define tr(node) tree[node]
using namespace std;
const int N = 3e4+ 7;
const int M = 50+7;
const int inf=0x3f3f3f;
const int mods =571373;
typedef long long ll;
int in[N];
int num[N];
int k=0;
int n,m;
vector<int>G[N];
bitset<N>dp[N];
int par[N];
int number[N];
int find(int x)
{
if(par[x]==x)
return x;
else
return par[x]=find(par[x]);
}
void unite(int u,int v)
{
int x=find(u),y=find(v);
if(x==y)
return ;
par[x]=y;
number[y]+=number[x];
}
void init()
{
for(int i=1; i<=n; i++)
{
par[i]=i;
number[i]=1;
}
}
int main()
{
int t;
int cnt=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
rep(i,1,m)
{
int u,v;
scanf("%d%d",&u,&v);
unite(u,v);
}
printf("Case #%d:\n",++cnt);
rep(i,1,n)
{
printf("%d ",number[find(i)]-1);
}
puts("");
}
return 0;
}
可达性统计
这次是有向图,不能用并查集来写。可以很容易想到对于
(
u
,
v
)
(
u
可
到
v
)
,
a
n
s
u
=
∑
a
n
s
v
(u,v)(u可到v),ans_u=\sum ans_v
(u,v)(u可到v),ansu=∑ansv,
所以可以用拓扑排序,从后往前遍历,或者dfs跑几遍,理论上可以直接一维dp做,但是判重很麻烦,懒得写了,等什么时候想起来,看看一维dp能不能。这里用bitset,(麻了又是二进制 ),又是熟悉的01表示能不能到达,最后用count函数获得1的数量就行了。
拓扑
#include <iostream>
#include <cstring>
#include <cmath>
#include <bitset>
#include <queue>
#include <vector>
#include <cstdio>
#include <set>
#include <stack>
#include <sstream>
#include <cstring>
#include <algorithm>
#include <map>
#define rep(i, a, b) for (long long i= a; i <= b; i++)
#define reps(i, a, b) for (long long i = a; i >= b; i--)
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/gcd(a,b)
#define ls(node) tree[node].ls
#define rs(node) tree[node].rs
#define val(node) tree[node].val
#define sum(node) tree[node].sum
#define lazy(node) tree[node].lazy
#define lazy1(node) tree[node].lazy1
#define lazy2(node) tree[node].lazy2
#define tr(node) tree[node]
using namespace std;
const int N = 3e4+ 7;
const int M = 50+7;
const int inf=0x3f3f3f;
const int mods =571373;
typedef long long ll;
int in[N];
int num[N];
int k=0;
int n,m;
vector<int>G[N];
bitset<N>dp[N];
void topo()
{
queue<int>q;
for(int i=1; i<=n; i++)
if(!in[i])
q.push(i);
while(!q.empty())
{
int u=q.front();
q.pop();
num[++k]=u;
for(int i=0; i<G[u].size(); i++)
{
int v=G[u][i];
in[v]--;
if(!in[v])
q.push(v);
}
}
}
int par[N];
int number[N];
int main()
{
scanf("%d%d",&n,&m);
rep(i,1,m)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
in[v]++;
}
topo();
reps(i,n,1)
{
int u=num[i];
dp[u][u]=1;
for(int j=0; j<G[u].size(); j++)
{
int v=G[u][j];
dp[u]|=dp[v];
}
}
rep(i,1,n)
{
printf("%d\n",dp[i].count());
}
return 0;
}
dfs
#include <iostream>
#include <cstring>
#include <cmath>
#include <bitset>
#include <queue>
#include <vector>
#include <cstdio>
#include <set>
#include <stack>
#include <sstream>
#include <cstring>
#include <algorithm>
#include <map>
#define rep(i, a, b) for (long long i= a; i <= b; i++)
#define reps(i, a, b) for (long long i = a; i >= b; i--)
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/gcd(a,b)
#define ls(node) tree[node].ls
#define rs(node) tree[node].rs
#define val(node) tree[node].val
#define sum(node) tree[node].sum
#define lazy(node) tree[node].lazy
#define lazy1(node) tree[node].lazy1
#define lazy2(node) tree[node].lazy2
#define tr(node) tree[node]
using namespace std;
const int N = 3e4+ 7;
const int M = 50+7;
const int inf=0x3f3f3f;
const int mods =571373;
typedef long long ll;
const int INF = 0x3f;
int in[N];
int num[N];
int k=0;
int n,m;
vector<int>G[N];
bitset<N>dp[N];
void dfs(int u)
{
dp[u][u]=1;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(dp[v].count()==0)dfs(v);//已经算过的就不用再算了,不然必t
dp[u]|=dp[v];
}
}
int main()
{
scanf("%d%d",&n,&m);
rep(i,1,m)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
in[v]++;
}
for(int i=1;i<=n;i++){
if(in[i]==0)dfs(i);
}
rep(i,1,n)
{
printf("%d\n",dp[i].count());
}
return 0;
}