1. 程式人生 > >Gym 101142C :CodeCoder vs TopForces(強連通算法)

Gym 101142C :CodeCoder vs TopForces(強連通算法)

clas tarjan return rst 關系 div top define 亂搞

題意:N個人,每個人有a屬性和b屬性,如果一個人的a或者b大於另外一個人,我們說這個人可以打敗那個人。且這種關系可以傳遞。對於每個人,輸出他可以打敗多少人。(保證每個a不相同,保證每個b不相同。

思路:對於a關系,我們按重小到大連邊,b同理。然後每個點能到的點就是可以打敗的點。即是縮點後亂搞。

(此題是圖,而不是排序後的數據結構題。

#include<bits/stdc++.h>
#define pii pair<int,int>
#define F first
#define S second
using namespace std;
const int
maxn=1000100; vector<int>G1[maxn],G2[maxn]; pii p1[maxn],p2[maxn]; int dfn[maxn],low[maxn],scc[maxn],scc_cnt,sz[maxn],ind[maxn]; int q[maxn],head,tail,times,ans[maxn],res[maxn],instk[maxn]; map<pii,int>mp; void tarjan(int u) { instk[u]=1; q[++head]=u; dfn[u]=low[u]=++times;
for(int i=0;i<G1[u].size();i++){ int v=G1[u][i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instk[v])low[u]=min(low[u],dfn[v]);//無向圖與有向圖的區別 } if(dfn[u]==low[u]){ scc_cnt++; while(true){
int x=q[head--]; scc[x]=scc_cnt; sz[scc_cnt]++; instk[x]=0; if(x==u) break; } } } int main() { int N,i,j; scanf("%d",&N); for(i=1;i<=N;i++) scanf("%d%d",&p1[i].F,&p2[i].F),p1[i].S=p2[i].S=i; sort(p1+1,p1+N+1); sort(p2+1,p2+N+1); for(i=2;i<=N;i++) G1[p1[i].S].push_back(p1[i-1].S); for(i=2;i<=N;i++) G1[p2[i].S].push_back(p2[i-1].S); for(i=1;i<=N;i++) if(!dfn[i]) tarjan(i); for(i=1;i<=N;i++){ int L=G1[i].size(); for(j=0;j<L;j++){ if(scc[i]!=scc[G1[i][j]]&&!mp[make_pair(scc[G1[i][j]],scc[i])]) mp[make_pair(scc[G1[i][j]],scc[i])]=1,G2[scc[G1[i][j]]].push_back(scc[i]),ind[scc[i]]++; } } head=tail=0; for(i=1;i<=scc_cnt;i++) if(ind[i]==0) q[++head]=i; while(tail<head){ int u=q[++tail]; int L=G2[u].size(); for(j=0;j<L;j++){ sz[G2[u][j]]+=sz[u]; if((--ind[G2[u][j]])==0) q[++head]=G2[u][j]; } } for(i=1;i<=N;i++) printf("%d\n",sz[scc[i]]-1); return 0; }

Gym 101142C :CodeCoder vs TopForces(強連通算法)