8.6 Round 1

依旧三道思维题,

 

T1:https://www.luogu.org/problem/T92260

失误:重复算了连通块之间的贡献,凉的彻底

考虑熔断一个点后,不可能把一个连通块拆成两个,或将一个环拆为两个(总有一种方法可以将其连回去)

所以对于所有度数>2的点,将其拆成若干个2和至多一个1

最后对于所有度数为1的点,将他们焊接在一起即可

考虑多个连通块:

1.如果一个连通块度数全为2,你需要额外熔断出两个度数为1的点

2.如果一个连通块度数全为偶数且存在度数比2大的点,不需要额外熔断,因为可以在熔断度数>2的点时,特别分出两个度数为1的点

最后答案就是拆点费用+度数=1点数/2

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<climits>
#include<map>
#include<queue>
using namespace std;
#define O(x) cout << #x << " " << x << endl;
#define B cout << "breakpoint" << endl;
#define clr(a) memset(a,0,sizeof(a));
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
const int maxn = 1e5 + 5;
int d[maxn];
bool vis[maxn];
struct egde
{
    int to,next;
}e[maxn << 1];
int fir[maxn],alloc;
void adde(int u,int v)
{
    d[u]++,d[v]++;
    e[++alloc].next = fir[u];
    fir[u] = alloc;
    e[alloc].to = v;
    swap(u,v);
    e[++alloc].next = fir[u];
    fir[u] = alloc;
    e[alloc].to = v;
}
int col[maxn];
bool all[maxn];
bool have[maxn];
void dfs(int u,int c)
{
    if(d[u] != 2) all[c] = 0;
    if(d[u] % 2) have[c] = 0;
    col[u] = c; vis[u] = 1;
    for(int i = fir[u];i;i = e[i].next)
    {
        int v = e[i].to;
        if(vis[v]) continue;
        dfs(v,c);
    }
}
int n,m;
int main()
{
    freopen("A.in","r",stdin);
    freopen("A.out","w",stdout);
    n = read(),m = read();
    for(int i = 1;i <= m;i++)
    {
        int u = read(),v = read();
        adde(u,v);
    }
    int cnt = 0;
    for(int i = 1;i <= n;i++) if(!col[i] && d[i]) all[++cnt] = 1,have[cnt] = 1,dfs(i,cnt);
    int tot = 0,ans = 0;
    for(int i = 1;i <= n;i++)
    {
        if(d[i] > 2) 
            tot += (d[i] % 2),ans++;
        else if(d[i] == 1) tot++;
    }
    if(cnt > 1) for(int i = 1;i <= cnt;i++) { if(have[i]) tot += 2; if(all[i]) ans++; }
    ans += tot / 2;
    //if(cnt >= 2) ans += cnt;
    printf("%d",ans);
}
/*
4 6
1 2
1 4
1 3
3 4
3 2
2 4
*/
    
View Code

 

T2:https://www.luogu.org/problem/T92261

失误:贪心没考虑好,结果错了...

正解是构造,令t=a+b-c,表示需要进位的位数

假设A全填1,讨论t与a的大小关系,再讨论t与b的大小关系

可以证明,当b填满1-a时,向后填更优

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<climits>
#include<map>
#include<queue>
using namespace std;
#define O(x) cout << #x << " " << x << endl;
#define B cout << "breakpoint" << endl;
#define clr(a) memset(a,0,sizeof(a));
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
const int maxn = 1e5 + 5;
int n,a,b,c;
int cnta[maxn],cntb[maxn],cntc[maxn];
void solve()
{
    if(c > a + b) { printf("-1\n"); exit(0); }
    int t = a + b - c;
    if(a < b) swap(a,b);
    if(t > a)
    {
        if(t >= b)
        {
            for(int i = 1;i <= a;i++) cnta[i] = 1;
            for(int i = a + 1;i <= t;i++) cntb[i] = 1;
            for(int i = 1;i <= c;i++) cntb[i] = 1;
        }
        else
        {
            for(int i = 1;i <= b;i++) cntb[i] = 1;
            for(int i = b - t + 1;i <= c;i++) cnta[i] = 1;    
        }
    }
    else
    {
        if(t >= b)
        {
            for(int i = 1;i <= a;i++) cnta[i] = 1;
            for(int i = a - t + 1;i <= c;i++) cntb[i] = 1;
        }
        else
        {
            int x = b - t;
            for(int i = x + 1;i <= a + x;i++) cnta[i] = 1;
            for(int i = 1;i <= x;i++) cntb[i] = 1;
            for(int i = c - t + 1;i <= c;i++) cntb[i] = 1;
        }
    }
    for(int i = 1;i <= n;i++)
    {
        cntc[i] += cnta[i] + cntb[i];
        cntc[i + 1] = cntc[i] / 2;
        cntc[i] %= 2;
    }
    if(cntc[n + 1]) { printf("-1\n"); exit(0); }
    for(int i = n;i >= 1;i--) printf("%d",cntc[i]); exit(0);
}
int main()
{
    freopen("B.in","r",stdin);
    freopen("B.out","w",stdout);
    n = read(),a = read(),b = read(),c = read();
    solve();
    /*if(a < b) swap(a,b);
    if(c > a + b)  { printf("-1\n"); return 0; }
    cnta[1] = cntb[1] = 1;
    int t = a + b - c;
    int ta = a - 1,tb = b - 1;
    for(int i = 2;i <= t;i++) 
    {
        if(!ta && !tb) { printf("-1\n"); return 0; }
        if(i % 2)
        {
             if(ta) cnta[i] = 1,ta--;
             else if(tb) cntb[i] = 1,tb--;
        }
        if(i % 2 == 0) 
        {
            if(tb) cntb[i] = 1,tb--;
            else if(ta) cnta[i] = 1,ta--;
        } 
    }
    for(int i = 1;i <= n;i++)
    {
        cntc[i] += cnta[i] + cntb[i];
        cntc[i + 1] = cntc[i] / 2;
        cntc[i] %= 2;
    }
    for(int i = 1;i <= n;i++)
    {
        if(ta) 
            if(!cntc[i] && !cnta[i]) cntc[i] = 1,ta--;
        if(tb) 
            if(!cntc[i] && !cntb[i]) cntc[i] = 1,tb--; 
    }
    if(cntc[n + 1]) { printf("-1\n"); return 0; }
    for(int i = n;i >= 1;i--) printf("%d",cntc[i]); return 0; 
    */
    
}
/*
6 4 1 2
*/
View Code

 

T3:咕

 

posted on 2019-08-07 14:28  L_M_A  阅读(109)  评论(0编辑  收藏  举报

导航