Codeforces 1038 E - Maximum Matching

本文探讨了欧拉图理论在解决特定图问题中的应用,通过分析度数为奇数的点及其对联通图中欧拉回路的影响,提出了在最坏情况下删除一条边以满足欧拉回路条件的方法,并设计了高效算法来枚举所有可能的边删除情况,最终确定最大匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

E - Maximum Matching

思路:

欧拉图

定理:一个度数为奇数的点的个数小于等于2的联通图存在欧拉回路

对于这道题目的图,点的个数为4,所以最坏的情况下4个点的度数都为奇数,在这种情况下只要删去一条边就可以满足条件了

欧拉回路算法:大圈小圈法,从起点开始跑每条边,把每条遍标记一下,直到跑到某个位置不能跑了,把点如栈,最后倒着输出

所以枚举删掉的边,跑联通图,最后判断联通图是否符合条件,复杂度:O(n^2)

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 120;
struct edge {
    int to, w, id;
};
vector<edge> g[N]; 
int d[5];
pii a[N];
bool vis[N], node[5];
LL ans, tot = 0;
void dfs(int u) {
    node[u] = true;
    for (int i = 0; i < g[u].size(); i++) {
        int id = g[u][i].id;
        if(!vis[id]) {
            vis[id] = true;
            dfs(g[u][i].to);
            tot += g[u][i].w;
        }
    }
}
int main() {
    int n, u, v, w;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d %d %d", &u, &w, &v);
        g[u].pb(edge{v, w, i});
        g[v].pb(edge{u, w, i});
        d[u]++;
        d[v]++;
        a[i].fi = u;
        a[i].se = v;
    }
    ans = 0;
    for (int i = 0; i <= n; i++) {
        if(i != 0 && a[i].fi == a[i].se) continue; 
        for (int j = 0; j <= n; j++) vis[j] = false;
        vis[i] = true;
        d[a[i].fi] --;
        d[a[i].se] --;
        for (int j = 1; j <= 4; j++) {
            tot = 0;
            mem(node, false);
            dfs(j);
            int cnt = 0;
            for (int k = 1; k <= 4; k++) if(node[k] && (d[k]&1)) cnt++;
            if(cnt <= 2)ans = max(ans, tot);
        }
        d[a[i].fi]++;
        d[a[i].se]++; 
    }
    printf("%lld\n", ans);
    return 0;
}

 

转载于:https://www.cnblogs.com/widsom/p/9649581.html

时间限制:1000ms 内存限制:512MB 输入文件名:s.in 输出文件名:s.out 题目描述: 给定一个长度为 N 的只含小写字母的字符串 S,每次操作可以选择一个位置 1 ≤ x ≤ N 和一个小写字母 c,接着把 Sₓ 改为 c。 你需要操作若干次,使得操作结束后,每相邻 K 个字符都不同,求最少的操作次数。保证 1 ≤ K ≤ 13。 输入格式: 第一行一个整数 T,表示测试数据组数。 接下来 T 组测试数据,对于每组测试数据: 第一行两个整数 N, K,分别表示字符串长度和子串的长度。 第二行一个长度为 N 的字符串 S。 输出格式: 对于每组测试数据,输出一行一个整数表示最少的操作次数。 样例输入 1(input1): 5 6 3 abaaba 5 2 hooch 8 3 cherykid 9 3 abbabbaba 9 3 aabbaabba 样例输出 1(output1): 2 1 0 3 4 样例 #1 解释: 对于第一组数据,可以用 2 次操作把 S 改为 abcabc,每相邻三个字符组成的字符串分别是 abc、bca、cab、abc,都满足包含的字符互不相同。 对于第三组数据,请注意可以不进行操作。 数据范围: 对于所有数据,保证 1 ≤ T ≤ 10⁵,1 ≤ ∑N ≤ 10⁶,1 ≤ K ≤ 13,S 中只含有小写字符。 子任务说明: 子任务 1:∑N ≤ 10,K ≤ 10,分值 10 子任务 2:∑N ≤ 100,K ≤ 10,分值 10 子任务 3:∑N ≤ 10³,K ≤ 13,分值 10 子任务 4:∑N ≤ 10⁵,K ≤ 3,分值 20 子任务 5:∑N ≤ 10⁵,K ≤ 13,分值 20 子任务 6:∑N ≤ 10⁶,K ≤ 13,分值 30 用C++ 14 With O2的语言写一段代码,不要超时,不要注释,用万能头,变量名用一个字母表示,最终代码写好后随便写5组边缘样例测试一下刚刚写的代码(把代码放进编译器输出检查),然后根据刚刚的代码测试修改代码,将这两段代码里的变量名用一个字母替代。代码加上空格,使代码有可读性(实在拿不到全分,也可以拿部分分,尽量多拿!)注意加上文件读写!!!!!!!!!!
07-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值