最大團演算法(codeforces839E)
阿新 • • 發佈:2019-02-15
題意理解玩,YY一下,就知道要把K平均分給最大團裡面的每個點,然後乘積和就是答案。
最大團就是有n個點的完全圖,完全圖就是n個點有n*(n-1)/2條邊的圖、有高效演算法求的。。
//最大獨立集:一個圖中最大的互相沒有邊相連的點集。 //結論:原圖的最大獨立集等於補圖的最大團 const int maxn=1010; int best; int num[maxn]; // int x[maxn]; int path[maxn]; int g[maxn][maxn], n; bool dfs( int *adj, int total, int cnt ){ // total: 與u相連的頂點數量 , cnt表示當前團的數量 int i, j, k; int t[maxn]; if( total == 0 ){ // 當此團中最後一個點 沒有 比起序號大 的頂點相連時 if( best < cnt ){ // 問題1:best為最大團中頂點的數量 // for( i = 0; i < cnt; i++) path[i] = x[i]; best = cnt; return true; } return false; } for( i = 0; i < total; i++){ // 列舉每一個與 u 相連的頂點 adj[i] if( cnt+(total-i) <= best ) return false; // 剪枝1, 若當前 頂點數量cnt 加上還能夠增加的最大數量 仍小於 best則 退出並返回false if( cnt+num[adj[i]] <= best ) return false; // 剪枝2, 若當前 頂點數量cnt 加上 包含adj[i]的最大團頂點數 仍小於 best則 退出並返回false // x[cnt] = adj[i]; for( k = 0, j = i+1; j < total; j++ ) // 掃描 與u相連的頂點 中與 adj[u]相連的頂點 並存儲到 陣列 t[]中,數量為k if( g[ adj[i] ][ adj[j] ] ) t[ k++ ] = adj[j]; if( dfs( t, k, cnt+1 ) ) return true; } return false; } int MaximumClique(){ int i, j, k; int adj[maxn]; if( n <= 0 ) return 0; best = 0; for( i = n-1; i >= 0; i-- ){ // x[0] = i; for( k = 0, j = i+1; j < n; j++ )// 遍歷 [i+1, n] 間頂點, if( g[i][j] ) adj[k++] = j; dfs( adj, k, 1 ); // *adj, total, cnt num[i] = best; // 得出頂點 i, 出發構成最大團 中頂點數量 } return best; } int main() { int k; cin >> n >> k; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) scanf("%d", &g[i][j]); int t = MaximumClique(); double ans = 0.5 * k * k * (t - 1) / t; printf("%.8lf\n", ans); return 0; }