13成都A Assignment For Princess

题意:在一个80个点的有向图中,现在已经知道了这个图的点数和边数,边的权值是从1-M,现在需要构造一张图,满足以下三个限制

(1) 从每一个点开始都可以到达另外任意一个点。

(2)从图中每一个点开始都可以回到自己。

(3) 图中的任意一个环上的权值和必须是3的倍数。

解法:这道构造题,在赛后听到了威哥他们说的解法,今天自己也是差不多这么写的,但是总是觉得怪怪的,就是刚开始我们先放一个大环罩住所有的点,然后再将其他的边加入到其中,那么大环怎么放是一个值得考虑的问题, 最后我的方法就是尽可能多的放1,2 这两种边,我也不知道为什么,然后不足的话放0补足,接下去还要插入一些剩余的边,我们就枚举pair(i,f) 然后在这个大环上如果i到f上的边权和模完3之后和我们要加的边模三属性是一样的话 ,就是可以放的,然后就把每一条边都插进去。然后就ac了 ,好奇怪 ,总觉得应该有什么更优美的方法。


#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <memory.h>
#include <vector>

using namespace std;

typedef pair<int,int> PII;

int n ,m;
#define maxn 85

bool use[maxn][maxn];
int ret[maxn][maxn];
vector<int> edge[3];
int sum[maxn];

void add(int u,int v,int w) {
    if(v > n) {
        ret[u][1] = w;
        use[u][1] = use[1][u] = true;
    }
    else {
        use[u][v] = use[v][u] = true;
        sum[v] = sum[v-1] + w;
        ret[u][v] = w;
    }
}

void debug() {
    for(int i = 1;i <= n;i++) {
        for(int f = 1;f <= n;f++)
            cout << use[i][f] << " " ;
        cout << endl;
    }
    cout << endl;
}

bool seek(int val) {
    for(int i = 1 ;i <= n;i++) 
        for(int f = 1;f <= n;f++) {
            if(i == f)
                continue;
            if(use[i][f] == true)
                continue;
            int tt = 0;
            if(f > i) {
                tt = sum[f] - sum[i];
                tt %= 3;
            }
            else {
                tt = sum[i] - sum[f];
                tt %= 3;
                tt = 3 - tt;
            }
            if(tt == (val % 3)) {
                use[i][f] = use[f][i] = true;
                ret[i][f] = val;
                return true;
            }
        }
    return false;
}

void ans() {
    for(int i = 1 ;i <= n;i++)
        for(int f = 0 ;f <= n;f++)
            if(0 != ret[i][f])
                printf("%d %d %d\n",i ,f, ret[i][f]);
}


bool solve() {
    int minn = min(edge[1].size() , edge[2].size());
    minn = min(minn , n / 2);
    int le = n - 2 * minn;
    if(le > edge[0].size())
        return false;
    for(int i = 0 ;i < minn;i ++) {
        add(i + 1, i + 2, *(edge[1].end()-1));
        edge[1].pop_back();
    }
    for(int i = 0 ;i < minn;i ++) {
        add(minn + i + 1,minn + i + 2,  *(edge[2].end()-1));
        edge[2].pop_back();
    }
    for(int i = 0;i < le ;i++) {
        add(2 * minn + i + 1,2 * minn + i + 2, *(edge[0].end()-1) );
        edge[0].pop_back();
    }
    for(int i = 0 ;i < 3;i++) {
        int size = edge[i].size();
        for(int f = 0 ;f < size;f++)
            if(false == seek(edge[i][f]))
                return false;
    }
    return true;
}

void init() {
    memset(use, false, sizeof(use));
    memset(ret, 0, sizeof(ret));
    edge[0].clear();
    edge[1].clear();
    edge[2].clear();

    memset(sum ,0, sizeof(sum));
    for(int i = 1;i <= m;i++)
        edge[i%3].push_back(i);
}

int main() {
    int cas;
    cin >> cas;
    for(int i = 0 ;i < cas;i++) {
        cin >> n >> m;
        printf("Case #%d:\n",i + 1);
        init();
        if(true == solve())
            ans();
        else
            cout << "-1" << endl;
    }
    return 0;
}

另外两道题目的代码:

06

#include <stdio.h>
#include <iostream>
#include <memory.h>
#include <queue>

using namespace std;

typedef pair<int,int> PII;
#define maxn 110000

PII b[maxn];
PII w[maxn];
int jb, jw;
int n ,m;

bool isfib[maxn];
int set[maxn];

int find(int x) {
    return set[x] == x ? x : set[x] = find(set[x]);
}

bool solve() {
    int minn = 0 ,maxx = 0;
    for(int i = 1;i <= n;i++)
        set[i] = i;    

    for(int i = 0;i < jb ;i++) {
        int u = b[i].first;
        int v = b[i].second;
        u = find(u);
        v = find(v);
        if(u != v)
            set[u] = v;
    }

    for(int i = 0;i < jw ;i++) {
        int u = w[i].first;
        int v = w[i].second;
        u = find(u);
        v = find(v);
        if(u != v) {
            set[u] = v;
            minn ++;
        }
    }

    int head = 0;
    for(int i = 1;i <= n; i++)
        if(set[i] == i)
            head ++;
    if(1 != head)
        return false;

    for(int i = 1;i <= n;i++)
        set[i] = i;    

    for(int i = 0;i < jw ;i++) {
        int u = w[i].first;
        int v = w[i].second;
        u = find(u);
        v = find(v);
        if(u != v) {
            set[u] = v;
            maxx ++;
        }
    }
    for(int i = minn;i <= maxx;i++)
        if(true == isfib[i])
            return true;
    return false;
}

void init() {
    int a = 1, b = 2; 
    memset(isfib , false ,sizeof(isfib));
    isfib[a] = true;
    while(b < maxn) {
        isfib[b] = true;
        int c = a + b;
        a = b;
        b = c;
    }
}

int main() {
    int cas;
    cin >> cas;
    int u ,v, t;

    init();

    for(int i = 0 ;i < cas;i++) {
        cin >> n >> m;
        jb = jw = 0;
        for(int f = 0 ;f < m;f++) {
            scanf("%d%d%d",&u, &v, &t);
            if(1 == t)
                w[jw ++ ] = make_pair(u,v);
            else
                b[jb ++ ] = make_pair(u,v);
        }
        bool ret = solve();
        printf("Case #%d: ", i + 1);
        if(true == ret)
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
    }
    return 0;
}

08

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <vector>
#include <string>

using namespace std;

string yu[9];

void init() {
    yu[0] = "B]";
    yu[1] = "KB]";
    yu[2] = "MB]";
    yu[3] = "GB]";
    yu[4] = "TB]";
    yu[5] = "PB]";
    yu[6] = "EB]";
    yu[7] = "ZB]";
    yu[8] = "YB]";
}

int main() {
    int a ,cas;
    cin >> cas;
    char ch[100];
    init();
    for(int i = 0 ;i < cas;i ++) {
        scanf("%d[%s",&a,ch);
        double l = 1;
        for(int i = 0 ;i < 9;i++) {
            if(yu[i] == ch)
                break;
            l *= (1000.0 / 1024);
        }
        printf("Case #%d: %.2lf%%\n",i + 1 , 100 - 100*l);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值