Day 1
卡牌游戲
這題是道簽到題,
容易想到把所有的 a , b a,b a,b 拿出來從小到大排序,然后列舉最小值,確定最大值,
先講一種很菜的 O ( n log ? 2 n ) O(n\log_2 n) O(nlog2?n) 做法,考慮 二分 最大值的位置,比這個最大值大的所有 a a a 顯然都要跳到它們對應的 b b b 處,可能還會出現不合法的情況,因此可以先用 后綴 維護出排序后下標在 [ i , 2 n ] [i,2n] [i,2n] 中的 a a a 對應的 b b b 的最大值,和 a a a 的個數,
其實還可以 O ( n ) O(n) O(n) 雙指標 ,因為最小值指標右移時,最大值指標不會左移,
如果忍受不了排序那個 O ( n log ? 2 n ) O(n\log_2 n) O(nlog2?n) ,可以 雙關鍵字桶排 ,
矩陣游戲
考慮先不管上下限,求出一組解,然后再進行調整,
求這一組解很簡單,可以令第一行、第一列全部為 0 0 0 ,然后按順序求出其他值即可,
怎么調整?發現對于任意一個 2 × 2 2\times 2 2×2 的矩陣,我們把其中的兩個 ? 1 -1 ?1 ,另外兩個 + 1 +1 +1 ,它們的和不變,仍然滿足 b b b 的限制,如果只修改一行,可以把這一行上列編號為奇數的元素 + x +x +x ,列編號為偶數的元素 ? x -x ?x ,對于每一列也是同理,
但是為什么這樣調整可以達到合法的狀態?
發現根據 b b b 矩陣我們可以列出 ( n ? 1 ) ( m ? 1 ) (n-1)(m-1) (n?1)(m?1) 個方程,此時距離解出 a a a 的值還差 n + m ? 1 n+m-1 n+m?1 個方程,因此如果我們確定了第一行和第一列所有元素的值,矩陣中的其它 a a a 的值就是固定的了,而顯然我們可以通過操作讓第一行、第一列的每一個元素達到任意取值,
那么我們怎么調整?
設第
i
i
i 行調整的數為
c
i
c_i
ci? ,第
i
i
i 列調整的數為
d
i
d_i
di? ,那么
a
i
,
j
′
=
a
i
,
j
+
(
?
1
)
j
+
1
c
i
+
(
?
1
)
i
+
1
d
j
a'_{i,j}=a_{i,j} + (-1)^{j+1} c_{i} + (-1)^{i+1} d_{j}
ai,j′?=ai,j?+(?1)j+1ci?+(?1)i+1dj?
發現當
i
,
j
i,j
i,j 的奇偶性相同時,
c
i
,
d
j
c_i,d_j
ci?,dj? 前面的系數相同,這時就是 和分約束 了,做不了,
因為我們只要讓相鄰的兩個數
c
,
d
c,d
c,d 的系數不同即可,因此可以
a
i
,
j
′
=
a
i
,
j
+
(
?
1
)
i
+
j
?
1
c
i
+
(
?
1
)
i
+
j
d
i
a'_{i,j}=a_{i,j} +(-1)^{i+j-1}c_i + (-1)^{i+j}d_i
ai,j′?=ai,j?+(?1)i+j?1ci?+(?1)i+jdi?
然后就是 差分約束 啦,
由于 差分約束 中我們建出來的是一個 完全二分圖 ,因此用 B e l l m a n ? F o r d Bellman-Ford Bellman?Ford 也可以跑得很快,
圖函式
不難想到, f ( u , G ) f(u,G) f(u,G) 表示圖 G G G 中有多少個點 v v v 滿足同時存在 u → v u\to v u→v 和 v → u v\to u v→u 且這兩條路徑上的點的編號都不小于 v v v ,
那么可以設 g i , j , k g_{i,j,k} gi,j,k? 表示當前的圖中是否存在路徑 i → j i\to j i→j 滿足路徑上的點的編號都不小于 k k k ,
如果用 F l o y d Floyd Floyd 做,可以省掉 k k k 這一維,從大到小列舉中轉點 k k k 即可,
發現 G G G 很煩,想辦法怎么一次 F l o y d Floyd Floyd 做完,
刪邊有點難搞,可以考慮把邊按編號從大到小插入,發現我們的狀態 g g g 記錄一個 b o o l bool bool 值,比較浪費,于是設 h i , j h_{i,j} hi,j? 表示當前的圖中,所有 i → j i\to j i→j 的路徑中 最大 的 路徑上最小的邊的編號 (省略 k k k 這一維),
用 F l o y d Floyd Floyd 做,可以求出一個答案的 差分陣列 ,求一個 后綴和 就好了,
雖然時間復雜度是 O ( n 3 ) O\left(n^3\right) O(n3) ,但是這卻是這題最快的解法,
盡管如此,可能還要卡卡常,下面給出一個小優化:
F l o y d Floyd Floyd 時, i , j > k i,j>k i,j>k 的情況更新狀態 h i , j h_{i,j} hi,j? 沒有意義了,
證明:
因為 i , j i,j i,j 不會再當中轉點了,且這兩個點都不會作為 k k k 對答案造成貢獻了,所以更新狀態 h i , j h_{i,j} hi,j? 沒有意義,
寶石
D a y ?? 2 Day\; 2 Day2 簽到題,然而我不會,
先考慮一條鏈上怎么做,我們先跳到 S → T S\to T S→T 中離 S S S 最近的顏色為 P 1 P_1 P1? 的點,然后跳離這個點最近的 P 2 P_2 P2? ,接著跳 P 3 P_3 P3? ……
那么現在要維護每個點后第一個顏色為 P 1 P_1 P1? 的點,以及這個點在寶石收集器中的下一種顏色對應的點,由于要跳很多步,用倍增優化跳的程序,
現在放到樹上,假設我們現在能 O ( 1 ) O(1) O(1) 求出任意一個點到根的路徑上離它最近的某種顏色的點,剩下的怎么做呢?老套路,把 S → T S\to T S→T 的路徑分成 S → l c a , l c a → T S\to lca,lca\to T S→lca,lca→T ,
先求在 S → l c a S\to lca S→lca 上最多能收集多少個寶石,這不是直接倍增往上跳就行了嗎?
再求在 l c a → T lca\to T lca→T 上最多能收集多少個寶石,不好做,于是把路徑反過來,二分收集到的最后一顆寶石,預處理出每個點在寶石收集器中的上一種顏色對應的點,也是倍增優化,這樣就可以 O ( log ? 2 c log ? 2 n ) O(\log_2 c\log_2 n) O(log2?clog2?n) 地求了,
發現這時這兩部分可以分開求,
于是把詢問離線,遍歷這棵樹兩次,每次都動態維護當前點到根的路徑上離它最近的某種顏色的點,第一次遍歷時求出 S → l c a S\to lca S→lca 這部分的答案,第二次遍歷時求出 l c a → T lca\to T lca→T 這部分的答案,這樣就可以了,
時間復雜度 O ( n log ? 2 n + q log ? 2 c log ? 2 n ) O(n\log_2 n+q\log_2 c\log_2 n) O(nlog2?n+qlog2?clog2?n) ,
P.S:這道題還可以用 點分治 做到 O ( n log ? 2 n + q log ? 2 n ) O(n\log_2 n+q\log_2 n) O(nlog2?n+qlog2?n) ,
滾榜
一眼看上去就是狀壓 D P DP DP ,
設 f s , i , j , k f_{s,i,j,k} fs,i,j,k? 表示狀態 s s s 中的隊伍還沒有公布,上一個公布的隊伍為 i i i , b i = j b_i=j bi?=j ,剩余的 m m m 值為 k k k ,
空間復雜度 O ( 2 n m 2 n ) O\left(2^n m^2 n\right) O(2nm2n) ,時間復雜度 O ( 2 n ? 2 m 2 n 2 ) O\left(2^{n-2}m^2 n^2\right) O(2n?2m2n2) ,勉強能拿 40 40 40 分,還不如暴力 O ( n × n ! ) O(n\times n!) O(n×n!) ,
考慮消掉一維,去掉 j j j ,由于 b b b 按公布順序單調不下降,可以在每次加入一個隊伍 x x x 之后強制把沒有公布的隊伍的 b b b 都加上 max ? ( a i ? a x + [ x > i ] , 0 ) \max\left(a_i-a_x+[x>i],0\right) max(ai??ax?+[x>i],0) ,這樣就行了,
空間復雜度 O ( 2 n m n ) O\left(2^nmn \right) O(2nmn),時間復雜度 O ( 2 n ? 2 m n 2 ) O\left(2^{n-2}mn^2\right) O(2n?2mn2) (實際上時間肯定是跑不滿的),
支配
考場上覺得這題可做,就拼命弄這題,結果因為一些地方想錯了,最后只拿到樹的 15 15 15 分,
發現對于每個點 x x x ,圖中必定存在一條鏈,使得鏈上包含所有在 D x D_x Dx? 中的點,若構建一個新圖 G 1 G_1 G1? ,若原圖 G 0 G_0 G0? 中 x x x 是 D y D_y Dy? 中離 y y y 最近的點(即走最少的步數能到達 y y y 的點),就在 G 1 G_1 G1? 中加入一條邊 x → y x\to y x→y ,發現 G 1 G_1 G1? 會變成一棵根節點是 1 1 1 的樹,事實上,這就是 支配樹 ,
怎么建這棵樹?有 O ( m ) O(m) O(m) 的做法,但是因為這題允許我們 O ( n 2 ) O\left(n^2\right) O(n2) 建樹,就不如用好寫的 O ( n 2 ) O\left(n^2\right) O(n2) 做法了,
可以從 1 1 1 到 n n n 列舉一個點 i i i ,然后從 1 1 1 出發,不經過 i i i 遍歷整個圖,若最后點 j j j 沒有被遍歷到,那么 i ∈ D j i\in D_j i∈Dj? ,顯然 i i i 的父親就是 D i D_i Di? 中 ∣ D ∣ |D| ∣D∣ 最小的點,
接下來考慮怎么求答案,
顯然就是求加入 s → t s\to t s→t 后有多少個點的受支集合發生改變(顯然受支集合只會減小,即去除某些元素),假設某個點 i i i 在支配樹上的子樹中的所有點的 D D D 發生了改變(這顯然是因為 D i D_i Di? 中一些元素不在 D s D_s Ds? 中),可以發現 i i i 要滿足兩個條件:
- f a i fa_i fai? 不在支配樹中 1 → s 1\to s 1→s 的路徑上,否則 D s ? D i D_s\subseteq D_i Ds??Di? ;
- 原圖中 t t t 不經過 f a i fa_i fai? 就可以到達 i i i ,否則新增的 1 → i 1\to i 1→i 的路徑仍然必經 D i D_i Di? 中的每一個點,
可以把原圖中的邊反向,對于點 i i i ,求出有哪些點 j j j 不經過 f a j fa_j faj? 就能到達 i i i ,就可以求出所有滿足 條件2 的點了,
列舉這些點,篩選出其中滿足 條件1 的點即可,
但是這些點可能已經在支配樹上形成祖孫關系了,這個差分處理即可,
時間復雜度 O ( n 2 + n q ) O\left(n^2 +nq \right) O(n2+nq) ,
代碼
card
#include<cstdio>
#include<algorithm>
using namespace std;
#define fo(i,l,r) for(i=l;i<=r;++i)
#define M 2000005
#define N 1000005
const int inf=1000000001;
int m,s,a[N][2],minn[M],maxx[M],sum[M];bool state[M];
struct node{int num,id;bool type;}b[M];
bool cmp(node x,node y){return x.num<y.num;}
inline int mymin(int x,int y){return x<y?x:y;}
inline int mymax(int x,int y){return x>y?x:y;}
int main()
{
freopen("card.in","r",stdin);
freopen("card.out","w",stdout);
register int i;
int n,ans=inf,l,r,mid,L=1,res;
scanf("%d%d",&n,&m);
fo(i,1,n) scanf("%d",&a[i][0]),b[++s]=(node){a[i][0],i,0};
fo(i,1,n) scanf("%d",&a[i][1]),b[++s]=(node){a[i][1],i,1};
sort(b+1,b+s+1,cmp);
fo(i,1,s) a[b[i].id][b[i].type]=i;
minn[s+1]=inf;
for(i=s;i;--i)
{
if(b[i].type)
minn[i]=minn[i+1],maxx[i]=maxx[i+1],sum[i]=sum[i+1];
else
{
minn[i]=mymin(minn[i+1],a[b[i].id][1]);
maxx[i]=mymax(maxx[i+1],a[b[i].id][1]);
sum[i]=sum[i+1]+1;
}
}
fo(i,1,s)
{
if(b[i].type&&!state[b[i].id]) --m,state[b[i].id]=1;
if(m<0) goto end;
l=L,r=s,res=-1;
while(l<=r)
{
mid=l+r>>1;
if(minn[mid+1]<i||maxx[mid+1]>mid||sum[mid+1]-(b[i].type&&a[b[i].id][0]>mid?1:0)>m) l=mid+1;
else r=mid-1,res=mid;
}
if(res>0&&b[res].num-b[i].num<ans) ans=b[res].num-b[i].num;
end:
if(b[i].type)
{
if(a[b[i].id][0]<i) break;
if(a[b[i].id][0]>L) L=a[b[i].id][0];
++m,state[b[i].id]=0;
}
else
{
if(a[b[i].id][1]<i) break;
if(a[b[i].id][1]>L) L=a[b[i].id][1];
--m,state[b[i].id]=1;
}
}
printf("%d\n",ans);
return 0;
}
matrix
#include<cstdio>
using namespace std;
#define fo(i,l,r) for(i=l;i<=r;++i)
#define fd(i,r,l) for(i=r;i>=l;--i)
#define N 305
char p[15],buf[100005],*l=buf,*r=buf;
inline char gc()
{return l==r&&(r=(l=buf)+fread(buf,1,100005,stdin),l==r)?EOF:*l++;}
inline void read(int &k)
{
char ch;while(ch=gc(),ch<'0'||ch>'9');k=ch-48;
while(ch=gc(),ch>='0'&&ch<='9') k=k*10+ch-48;
}
inline void print(int x)
{
if(!x) putchar('0');
else
{
int len=0;
while(x) p[++len]=x%10+48,x/=10;
for(;len;--len) putchar(p[len]);
}
putchar(' ');
}
int a[N][N],b[N][N],wa[N][N],wb[N][N],fa[N],fb[N];
inline void mymin(int &x,int y){if(x>y) x=y;}
int main()
{
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
register int i,j;
int T,n,m,s,x,y;
bool flag;
read(T);
while(T--)
{
read(n),read(m);
for(i=1;i<n;++i)
for(j=1;j<m;++j) read(b[i][j]);
fo(i,1,n) a[i][1]=0;
fo(i,1,m) a[1][i]=0;
fo(i,2,n) fo(j,2,m) a[i][j]=b[i-1][j-1]-a[i][j-1]-a[i-1][j]-a[i-1][j-1];
s=n+m;
fo(i,1,n) fo(j,1,m) wa[i][j]=wb[j][i]=0x3f3f3f3f;
fo(i,1,n) fa[i]=0;
fo(i,1,m) fb[i]=0;
fo(i,1,n) fo(j,1,m)
{
if(i+j&1) // d[j]-c[i]
{
mymin(wa[i][j],a[i][j]),
mymin(wb[j][i],1000000-a[i][j]);
}
else // c[i]-d[j]
{
mymin(wb[j][i],a[i][j]),
mymin(wa[i][j],1000000-a[i][j]);
}
}
fo(x,1,s)
{
flag=1;
fo(i,1,n) fo(j,1,m)
if(fa[i]>fb[j]+wb[j][i])
fa[i]=fb[j]+wb[j][i],flag=0;
fo(i,1,m) fo(j,1,n)
if(fb[i]>fa[j]+wa[j][i])
fb[i]=fa[j]+wa[j][i],flag=0;
if(flag) break;
}
if(x>s) goto out;
fo(i,1,n) fo(j,1,m)
{
a[i][j]=i+j&1?a[i][j]+fa[i]-fb[j]:a[i][j]-fa[i]+fb[j];
if(a[i][j]<0||a[i][j]>1000000) goto out;
}
puts("YES");
fo(i,1,n)
{
fo(j,1,m) print(a[i][j]);
putchar('\n');
}
continue;
out:puts("NO");
}
return 0;
}
graph
#include<cstdio>
using namespace std;
#define M 200005
#define N 1005
char p[15],buf[100005],*pl=buf,*pr=buf;
inline char gc()
{return pl==pr&&(pr=(pl=buf)+fread(buf,1,100005,stdin),pl==pr)?EOF:*pl++;}
inline void read(int &k)
{
char ch;while(ch=gc(),ch<'0'||ch>'9');k=ch-48;
while(ch=gc(),ch>='0'&&ch<='9') k=k*10+ch-48;
}
inline void print(int x)
{
if(!x) putchar('0');
else
{
int len=0;
while(x) p[++len]=x%10+48,x/=10;
for(;len;--len) putchar(p[len]);
}
putchar(' ');
}
int f[N][N],ans[M];
inline int mymin(int x,int y){return x<y?x:y;}
inline void mymax(int &x,int y){if(x<y) x=y;}
int main()
{
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
register int i,j,k,tmp;
int x,y,n,m;
read(n),read(m);
for(i=1;i<=m;++i) read(x),read(y),f[x][y]=i;
for(k=n;k;--k)
{
for(i=k+1;i<=n;++i) ++ans[mymin(f[i][k],f[k][i])];
for(i=1;i<k;++i) if(f[i][k])
for(j=1;j<=n;++j)
mymax(f[i][j],mymin(f[i][k],f[k][j]));
for(i=k+1;i<=n;++i) if(f[i][k])
for(j=1;j<k;++j)
mymax(f[i][j],mymin(f[i][k],f[k][j]));
// i,j>k 因為 i,j 不會再當中轉點了,且這兩個點都不會作為 k 對答案造成貢獻了,所以沒有意義
}
ans[m+1]=n;
for(i=m;i;--i) ans[i]+=ans[i+1];
for(i=1;i<=m+1;++i) print(ans[i]);
return 0;
}
gem
#include<cstdio>
#include<vector>
using namespace std;
char p[15],buf[100005],*pl=buf,*pr=buf;
inline char gc()
{return pl==pr&&(pr=(pl=buf)+fread(buf,1,100005,stdin),pl==pr)?EOF:*pl++;}
inline void read(int &k)
{
char ch;while(ch=gc(),ch<'0'||ch>'9');k=ch-48;
while(ch=gc(),ch>='0'&&ch<='9') k=k*10+ch-48;
}
inline void print(int x)
{
if(!x) putchar('0');
else
{
int len=0;
while(x) p[++len]=x%10+48,x/=10;
for(;len;--len) putchar(p[len]);
}
putchar('\n');
}
#define fo(i,l,r) for(i=l;i<=r;++i)
#define M 400005
#define N 200005
#define C 50005
int fir[N],to[M],nex[M],w[N],num[C],id[C],las[C],f[N][18],g[N][18],h[N][18],dep[N],c,q,s,l,r,mid,now,res;
struct node{int st,ed,lca,mid,ans;}a[N];
vector<int>qry1[N],qry2[N];
inline void inc(int x,int y)
{
to[++s]=y,nex[s]=fir[x],fir[x]=s;
to[++s]=x,nex[s]=fir[y],fir[y]=s;
}
void dfs(int k)
{
int i,tmp=las[w[k]];
dep[k]=dep[f[k][0]]+1;
g[k][0]=las[num[id[w[k]]+1]],
h[k][0]=id[w[k]]?las[num[id[w[k]]-1]]:0;
las[w[k]]=k;
for(i=fir[k];i;i=nex[i])
if(to[i]!=f[k][0])
f[to[i]][0]=k,dfs(to[i]);
las[w[k]]=tmp;
}
inline void swap(int &x,int &y){int z=x;x=y,y=z;}
inline int getlca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
for(int i=17;i>=0;--i)
if(dep[f[u][i]]>=dep[v])
u=f[u][i];
if(u==v) return u;
for(int i=17;i>=0;--i)
if(f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
return f[u][0];
}
void solveL(int k)
{
int i,j,tmp;
for(i=0;i<qry1[k].size();++i)
{
now=qry1[k][i],
tmp=w[k]==num[1]?k:las[num[1]];
for(j=17;j>=0;--j)
if(dep[g[tmp][j]]>=dep[a[now].lca])
tmp=g[tmp][j];
a[now].mid=dep[tmp]>=dep[a[now].lca]?w[tmp]:0;
}
tmp=las[w[k]],las[w[k]]=k;
for(i=fir[k];i;i=nex[i])
if(to[i]!=f[k][0]) solveL(to[i]);
las[w[k]]=tmp;
}
void solveR(int k)
{
int i,j,tmp;
for(i=0;i<qry2[k].size();++i)
{
now=qry2[k][i],l=id[a[now].mid]+1,r=c,res=l-1;
while(l<=r)
{
mid=l+r>>1,
tmp=w[k]==num[mid]?k:las[num[mid]];
for(j=17;j>=0;--j)
if(dep[h[tmp][j]]>=dep[a[now].lca])
tmp=h[tmp][j];
if(dep[tmp]>=dep[a[now].lca]&&id[w[tmp]]<=id[a[now].mid]+1) res=mid,l=mid+1;
else r=mid-1;
}
a[now].ans=res;
}
tmp=las[w[k]],las[w[k]]=k;
for(i=fir[k];i;i=nex[i])
if(to[i]!=f[k][0]) solveR(to[i]);
las[w[k]]=tmp;
}
int main()
{
freopen("gem.in","r",stdin);
freopen("gem.out","w",stdout);
register int i;
int j,n,m,x,y;
read(n),read(m),read(c);
fo(i,1,c) read(num[i]),id[num[i]]=i;
fo(i,1,n) read(w[i]);
for(i=1;i<n;++i) read(x),read(y),inc(x,y);
dfs(1);
fo(j,1,17) fo(i,1,n)
f[i][j]=f[f[i][j-1]][j-1],
g[i][j]=g[g[i][j-1]][j-1],
h[i][j]=h[h[i][j-1]][j-1];
read(q);
fo(i,1,q)
read(a[i].st),read(a[i].ed),
a[i].lca=getlca(a[i].st,a[i].ed),
qry1[a[i].st].push_back(i),
qry2[a[i].ed].push_back(i);
fo(i,1,m) las[i]=0;solveL(1);
fo(i,1,m) las[i]=0;solveR(1);
fo(i,1,q) print(a[i].ans);
return 0;
}
ranklist
#include<cstdio>
using namespace std;
#define fo(i,l,r) for(i=l;i<=r;++i)
#define fd(i,r,l) for(i=r;i>=l;--i)
#define M 505
#define N 15
long long f[8195][N][M];
int a[N];
int main()
{
freopen("ranklist.in","r",stdin);
freopen("ranklist.out","w",stdout);
register int k,j,i;
int s,t,len,n,m,S,tmp,max=0;
long long ans=0;
scanf("%d%d",&n,&m),a[0]=-1;
fo(i,1,n) scanf("%d",a+i);
fo(i,1,n) if(a[i]>a[max]) max=i;
S=(1<<n)-1;
fo(i,1,n)
{
tmp=n*(a[max]-a[i]+(max<i));
if(tmp<=m) f[S^1<<i-1][i][m-tmp]=1;
}
fd(s,S-1,1)
{
len=0;
fo(i,1,n) if(s&1<<i-1) ++len;
fo(i,1,n) if(!(s&1<<i-1))
fo(k,1,n) if(s&1<<k-1)
{
tmp=(a[i]-a[k]+(i<k))*len;
t=s^1<<k-1;
if(tmp<0) tmp=0;
fo(j,tmp,m) if(f[s][i][j])
f[t][k][j-tmp]+=f[s][i][j];
}
}
fo(i,1,n) fo(j,0,m) ans+=f[0][i][j];
printf("%lld\n",ans);
return 0;
}
dominator
#include<cstdio>
#include<algorithm>
using namespace std;
#define fo(i,l,r) for(i=l;i<=r;++i)
#define M 6005
#define N 3005
struct graph
{
int fir[N],to[M],nex[M],s;
inline void inc(int x,int y)
{to[++s]=y,nex[s]=fir[x],fir[x]=s;}
}G,F,D_tree;
struct node
{
int D[N],siz;
inline void inc(int x){D[++siz]=x;}
}a[N],list[N];
int fa[N],vis[N],siz[N],dfn[N],sum[N],ord,time;
bool b[N],in[N];
void dfs1(int k)
{
vis[k]=time;
for(int i=G.fir[k];i;i=G.nex[i])
if(b[G.to[i]]&&vis[G.to[i]]<time)
dfs1(G.to[i]);
}
void dfs2(int k)
{
vis[k]=time,list[k].inc(time);
for(int i=F.fir[k];i;i=F.nex[i])
if(b[F.to[i]]&&vis[F.to[i]]<time)
dfs2(F.to[i]);
}
void dfs3(int k)
{
siz[k]=1,dfn[k]=++ord;
for(int i=D_tree.fir[k];i;i=D_tree.nex[i])
dfs3(D_tree.to[i]),siz[k]+=siz[D_tree.to[i]];
}
int main()
{
freopen("dominator.in","r",stdin);
freopen("dominator.out","w",stdout);
register int i,j;
int n,m,q,x,y,ans,k;
scanf("%d%d%d",&n,&m,&q);
fo(i,1,m)
scanf("%d%d",&x,&y),
G.inc(x,y),F.inc(y,x);
fo(i,1,n) b[i]=1;
fo(i,2,n)
{
a[i].inc(1);
time=i,b[i]=0,
dfs1(1),vis[i]=i;
fo(j,2,n) if(vis[j]<i)
a[j].inc(i);
b[i]=1;
}
fo(i,2,n)
{
fa[i]=a[i].D[1];
fo(j,2,a[i].siz)
if(a[a[i].D[j]].siz>a[fa[i]].siz)
fa[i]=a[i].D[j];
}
fo(i,2,n) D_tree.inc(fa[i],i);
dfs3(1);
fo(i,1,n) vis[i]=0;
fo(i,2,n)
{
time=i,b[fa[i]]=0;
dfs2(i),b[fa[i]]=1;
}
b[0]=1;
while(q--)
{
scanf("%d%d",&x,&y),ans=0;
fo(i,1,n) sum[i]=0;
i=x,b[1]=0;while(i>1) b[i]=0,i=fa[i];
fo(j,1,list[y].siz)
{
k=list[y].D[j];
if(b[fa[k]]) ++sum[dfn[k]],--sum[dfn[k]+siz[k]];
}
fo(j,1,n)
{
sum[j]+=sum[j-1];
if(sum[j]) ++ans;
}
printf("%d\n",ans);
i=x,b[1]=1;while(i>1) b[i]=1,i=fa[i];
}
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/279335.html
標籤:其他
上一篇:性能優化篇之腳本策略
