#include
#include
#include
using
namespace
std;
/*tarjan演算法
對於a和b分別建圖,讓i與ai連邊、i與bi連邊
計算圖強連通分量的個數cnt_a,cnt_b和各個強連通分量包含點的個數num_a,num_b
如果num_a>=num_b&&num_a%num_b==0 說明值域中num_b個數可以代入num_a個遞推式
*/const
int maxn=1e5+5;//點數
const
int mod=1e9+7;
struct edge
edge[maxn];
int head[maxn],tot;
//belong 陣列的值是1~scc
int low[maxn],dfn[maxn],stack[maxn],belong[maxn];
int index,top;
int scc;//強連通分量的個數
bool instack[maxn];
int num[maxn];//各個強連通分量包含點的個數,陣列編號1~scc
int n,m;
int num_a[maxn];
int num_b[maxn];
int cnt_a,cnt_b;
void addage(int u,int v)
void tarjan(int u)
else
if(instack[v]&&low[u]>dfn[v])
}if(low[u]==dfn[u])
while(v!=u);
}}void solve(int n)
}}void init()
int main()
solve(n);
cnt_a=scc;
for(int i=1;i<=scc;i++)
init();
for(int i=0;iscanf("%d",&x);
addage(i,x);
}solve(m);
cnt_b=scc;
for(int i=1;i<=scc;i++)
int ans=1;
int tmp=0;
//printf("cnt_a=%d cnt_b=%d\n",cnt_a,cnt_b);
for(int i=0;i0;//有cnt_a個遞推式時,函式可以有tmp個
for(int j=0;j//printf("a=%d b=%d\n",num_a[i],num_b[j]);
if(num_a[i]>=num_b[j]&&num_a[i]%num_b[j]==0)
}//printf("tmp=%d\n",tmp);
ans=(ans*tmp)%mod;
}printf("case #%d: %d\n",kase++,ans);
}return
0;}
HDU 6038 Function 找迴圈節
這題比賽的時候題意就看了半天,看到最後看懂了,感覺是找迴圈但是不知道怎麼處理,也沒再做。比完賽對著標程看才明白這題的做法。題意是說有兩個陣列a,b,他們之間滿足關係式 因為要求找出相互之間的對應關係的種數,再通過例子,便想著是要找迴圈來找出對應關係。因為a可以和f函式的順序構成關係,所以以a為固定,...
hdu 4612 強連通分量
題意 有一些小島,這些小島上有一些邊,讓你加一條邊,使得原先的那些邊的橋數最少。做法 1,把小島為點,連線小島的為邊建圖。2,求出圖中的所有強聯通分量 3,把所有的強聯通分量看成乙個點建樹。4,求樹的直徑,新加的那條邊應該在直徑的兩邊,這樣才能使得圖中的橋最小。pragma comment link...
HDU 3072 強連通分量
題目鏈結 題目大意 為乙個有向連通圖加邊。使得整個圖全連通,有重邊出現。解題思路 先用tarjan把強連通分量縮點。由於整個圖肯定是連通的,所以列舉每一條邊,記錄到非0這個點所在連通分量的最小cost。一共需要累加cnt 1個連通分量的cost。在tarjan過程中的重邊,可以用鏈式前向星結構解決。...