HDU 6073 Matching In Multiplication dfs遍历环 + 拓扑

Matching In Multiplication

Problem Description
In the mathematical discipline of graph theory, a bipartite graph is a graph whose vertices can be divided into two disjoint sets U and V (that is, U and V are each independent sets) such that every edge connects a vertex in U to one in V. Vertex sets U and V are usually called the parts of the graph. Equivalently, a bipartite graph is a graph that does not contain any odd-length cycles. A matching in a graph is a set of edges without common vertices. A perfect matching is a matching that each vertice is covered by an edge in the set.

                       

Little Q misunderstands the definition of bipartite graph, he thinks the size of U is equal to the size of V, and for each vertex p in U, there are exactly two edges from p. Based on such weighted graph, he defines the weight of a perfect matching as the product of all the edges‘ weight, and the weight of a graph is the sum of all the perfect matchings‘ weight.

Please write a program to compute the weight of a weighted ‘‘bipartite graph‘‘ made by Little Q.

Input
The first line of the input contains an integer T(1≤T≤15), denoting the number of test cases.

In each test case, there is an integer n(1≤n≤300000) in the first line, denoting the size of U. The vertex in U and V are labeled by 1,2,...,n.

For the next n lines, each line contains 4 integers vi,1,wi,1,vi,2,wi,2(1≤vi,j≤n,1≤wi,j≤109), denoting there is an edge between Ui and Vvi,1, weighted wi,1, and there is another edge between Ui and Vvi,2, weighted wi,2.

It is guaranteed that each graph has at least one perfect matchings, and there are at most one edge between every pair of vertex.

Output
For each test case, print a single line containing an integer, denoting the weight of the given graph. Since the answer may be very large, please print the answer modulo 998244353.

Sample Input
1
2
2 1 1 4
1 4 2 3

Sample Output
16

题意:

  给你一个图,n点 2*n边,有边权。

  左边的1~n个点出度都为2,且都连向右边的点,两点之间,没有重边,求出每种完美匹配下各边乘积的总和

题解:

  不好好写就会wa死你哦,咕咕咕

  首先如果一个点的度数为11,那么它的匹配方案是固定的,继而我们可以去掉这一对点。通过拓扑我们可以不断去掉所有度数为11的点。

  那么剩下的图中左右各有mm个点,每个点度数都不小于22,且左边每个点度数都是22,而右侧总度数是2m2m,

  因此右侧只能是每个点度数都是22。这说明这个图每个连通块是个环,在环上间隔着取即可,一共两种方案。

  时间复杂度O(n)O(n)

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N = 1e6+10, M = 1e3+20,inf = 2e9;

const LL mod = 998244353LL;

queue<pii > q;
int vis[N],done[N],d[N],n,T,zhong;
LL ans1,ans2;
vector<pii > G[N];
void init() {
    for(int i = 0; i <= 2*n; ++i)
        G[i].clear(),vis[i] = 0,done[i] = 0,d[i] = 0;
}
void dfs(int u,int f,int p) {
    vis[u] = 1;
    int flag = 1;
    for(int i = 0; i < G[u].size(); ++i) {
        int to = G[u][i].first;
        if(vis[to]) continue;
        flag = 0;
        if(!p) ans1 = 1LL * ans1 * G[u][i].second % mod;
        else ans2 = 1LL * ans2 * G[u][i].second % mod;
        dfs(to,u,1 - p);
    }
    if(flag) {
        for(int i = 0; i < G[u].size(); ++i) {
            int to = G[u][i].first;
            if(to != zhong) continue;
            if(!p) ans1 = 1LL * ans1 * G[u][i].second % mod;
            else ans2 = 1LL * ans2 * G[u][i].second % mod;
        }
    }
}
void make_faiil(int u,int f,int p) {
    done[u] = 1;
    vis[u] =1;
    for(int i = 0; i < G[u].size(); ++i) {
        int to = G[u][i].first;
        if(to == f || done[to]) continue;
        make_faiil(to,u,1 - p);
    }
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        init();
        for(int i = 1; i <= n; ++i) {
            int x,y;
            scanf("%d%d",&x,&y);
            d[i] += 1;
            d[x + n] += 1;
            G[i].push_back(MP(x + n,y));
            G[x + n].push_back(MP(i,y));

            scanf("%d%d",&x,&y);
            d[i] += 1;
            d[x + n] += 1;
            G[i].push_back(MP(x + n,y));
            G[x + n].push_back(MP(i,y));
        }
        int ok = 1;
        while(!q.empty()) q.pop();
        for(int i = n+1; i <= 2*n; ++i) {
            if(d[i] == 1) {
                q.push(MP(i,0));
                vis[i] = 1;
            }
        }
        LL ans = 1LL;
        while(!q.empty()) {
            pii k = q.front();
            q.pop();
            for(int i = 0; i < G[k.first].size(); ++i) {
                int to = G[k.first][i].first;
                if(vis[to]) continue;
                d[to] -= 1;
                if(d[to] == 1) {
                    if(!k.second)ans = ans * G[k.first][i].second % mod;
                    q.push(MP(to,!k.second));
                    vis[to] = 1;
                }
            }
        }
        //cout<<ans<<endl;
        LL tmp1 = ans,tmp2 = 0;
        for(int i = 1; i <= 2*n; ++i) {
            if(!vis[i]){
              //  cout<<"huasndina " << i<<endl;
                ans1 = 1LL,ans2 = 1LL;
                zhong = i;
                dfs(i,-1,0);
                LL tmptmp = (ans1 + ans2) % mod;
                ans = ans * tmptmp % mod;
            }
        }
        printf("%lld\n",(ans)%mod);
    }
    return 0;
}

/*
10
5
1 1 2 3
1 2 3 4
3 5 4 7
3 6 4 8
4 9 5 104920
*/
时间: 2025-01-03 22:01:47

HDU 6073 Matching In Multiplication dfs遍历环 + 拓扑的相关文章

HDU 6073 Matching In Multiplication —— 2017 Multi-University Training 4

Matching In Multiplication Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 1389    Accepted Submission(s): 423 Problem Description In the mathematical discipline of graph theory, a bipartite g

HDU 6073 Matching In Multiplication(拓扑排序)

Matching In Multiplication Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 1127    Accepted Submission(s): 325 Problem Description In the mathematical discipline of graph theory, a bipartite g

HDU 1241 Oil Deposits --- 入门DFS

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1241 /* HDU 1241 Oil Deposits --- 入门DFS */ #include <cstdio> int m, n; //n行m列 char mapp[105][105]; /* 将和i,j同处于一个连通块的字符标记出来 */ void dfs(int i, int j){ if (i < 0 || j < 0 || i >= n || j >= m

HDU 2553(N皇后)(DFS)

http://acm.hdu.edu.cn/showproblem.php?pid=2553 i表示行,map[i]表示列,然后用DFS遍历回溯 可以参考这篇文章: http://blog.csdn.net/cambridgeacm/article/details/7703739 1 #include <iostream> 2 #include <string> 3 #include <cstring> 4 #include <cstdlib> 5 #inc

HDU 哈密顿绕行世界问题 (dfs)

Problem Description 一个规则的实心十二面体,它的 20个顶点标出世界著名的20个城市,你从一个城市出发经过每个城市刚好一次后回到出发的城市. Input 前20行的第i行有3个数,表示与第i个城市相邻的3个城市.第20行以后每行有1个数m,m<=20,m>=1.m=0退出. Output 输出从第m个城市出发经过每个城市1次又回到m的所有路线,如有多条路线,按字典序输出,每行1条路线.每行首先输出是第几条路线.然后个一个: 后列出经过的城市.参看Sample output

矩阵乘法 --- hdu 4920 : Matrix multiplication

Matrix multiplication Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 820    Accepted Submission(s): 328 Problem Description Given two matrices A and B of size n×n, find the product of them. b

hdu 2489 Minimal Ratio Tree(dfs枚举 + 最小生成树)~~~

题目: 链接:点击打开链接 题意: 输入n个点,要求选m个点满足连接m个点的m-1条边权值和sum与点的权值和ans使得sum/ans最小,并输出所选的m个点,如果有多种情况就选第一个点最小的,如果第一个点也相同就选第二个点最小的........ 思路: 求一个图中的一颗子树,使得Sum(edge weight)/Sum(point weight)最小~ 数据量小,暴力枚举~~~~~dfs暴力枚举C(M,N)种情况. 枚举出这M个点之后,Sum(point weight)固定,进行prim或者K

图的邻接表存储c实现(DFS遍历)

先简要列出实现过程中所需要的数据结构. 如下图 对于这个图而言,它的邻接表可以这样表示,当然表现形式可以多样,这只是我随便画的一种表示方法. 顶点表                                          边表 我们把第一个表即上面标着fixedvex的这个表称作顶点表,后边的称为边表. 上图所示,边表的结构应该这样写: //定义一个边表节点的结构 typedef struct node{ int adjvex; //int Mark; //用于标记是否被访问过 nod

HDU 1010 Tempter of Bone DFS + 奇偶剪枝

奇偶剪枝: 对于从起始点 s 到达 终点 e,走且只走 t 步的可达性问题的一种剪枝策略. 如下列矩阵 : 从任意 0 到达 任意 0,所需步数均为偶数,到达任意 1 ,均为奇数.反之亦然 所以有,若s走且只走 t 步可到达e,则必有t >= abs(s.x - e.x) + abs(s.y - e.y),且 (t&1) == ((abs(s.x - e.x) + abs(s.y - e.y))&1). 否则必不可达. #include <iostream> #inclu