暴力搜索 + 剪枝


A clique is a complete graph, in which there is an edge between every pair of the vertices. Given a graph with NNN vertices and MMM edges, your task is to count the number of cliques with a specific size SSS in the graph.

Input

The first line is the number of test cases. For each test case, the first line contains 333 integers N,MN,MN,M and SSS (N≤100,M≤1000,2≤S≤10)(N \le 100,M \le 1000,2 \le S \le 10)(N100,M1000,2S10), each of the following MMM lines contains 222 integers uuu and vvv (1≤u<v≤N)(1 \le u < v \le N)(1u<vN), which means there is an edge between vertices uuu and vvv. It is guaranteed that the maximum degree of the vertices is no larger than 202020.

Output

For each test case, output the number of cliques with size SSS in the graph.

樣例輸入

3
4 3 2
1 2
2 3
3 4
5 9 3
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
6 15 4
1 2
1 3
1 4
1 5
1 6
2 3
2 4
2 5
2 6
3 4
3 5
3 6
4 5
4 6
5 6

樣例輸出

3
7
15

題意 : 給你一張圖,詢問這個圖中有多少個大小為 s 的完全子圖
思路分析 : 因為數據比較小,因此我們直接暴力去找就可以了,對於選出的任意一個子圖,只需要判斷任意兩條邊是否都有邊即可, 但是只是單純的這樣操作會超時,因為尋找了很多無用的狀態,例如 1, 3, 5
大小為 3 的完全圖,我們再尋找的過程中 1, 5, 3也會被找到,其實本質上是同一個完全子圖,這里我們只需要在建邊的時候優化一下就可以了,建的時候我們只建立單向的邊,即從小到大的方向上面建邊
代碼示例 :

int n, m, k;
vector<int>ve[105];
int mp[105][105];
int f[105];
int ans = 0;
int vis[105];
struct edg
{
    int to, next;    
}edge[1005];
int head[1005];
int cnt = 1;

void addedge(int u, int v){
    edge[cnt].next = head[u];    
    edge[cnt].to = v;
    head[u] = cnt++;
}

void dfs(int x, int fa, int cnt){
    int sign = 0;
    for(int i = 1; i < cnt; i++){
        if (mp[x][f[i]] == 0) {sign = 1; break;}
    }    
    if (sign) return;
    f[cnt] = x; 
    
    if (cnt == k) {ans++; return;}
    for(int i = head[x]; i != -1; i = edge[i].next){
        int to = edge[i].to;
        if (to == fa) continue;
        int sign = 0;
        if (!vis[to]) { 
            vis[to] = 1;
            dfs(to, x, cnt+1);
            vis[to] = 0;
        }
    }
}

int main() { 
    int t;
    int a, b;
    
    cin >> t;
    while(t--){
        scanf("%d%d%d", &n, &m, &k);
        memset(mp, 0, sizeof(mp));
        memset(vis, 0, sizeof(vis));
        
        memset(head, -1, sizeof(head));
        cnt = 1;
        for(int i = 1; i <= m; i++){
            scanf("%d%d", &a, &b);
            if (a > b) swap(a, b);
            addedge(a, b);
            mp[a][b] = mp[b][a] = 1;            
        }
        ans = 0;
        for(int i = 1; i <= n; i++){
            dfs(i, 0, 1); 
        }
        printf("%d\n", ans);
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM