Codeforces Round #285(Div.2) A,B,C 解题报告

转载请注明出处,谢谢:
http://blog.csdn.net/wybluewind/article/details/47818925

codeforces 上的题解:http://codeforces.com/blog/entry/15743


A. Contest

题目大意:
        Codeforces比赛中,Misha在c分钟过了a分的题,Vasya在d分钟过了b分的题。最终的得分的计算方法:max(3p/10, p-pt/250)[在t分钟过了p分的题];

思路:
        简单,带入公式算一下就行,注意:不是int类型。

代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;

    double a,b,c,d;
    double m,v;

    int main()
    {
    //    freopen("in.txt","r",stdin);
        while(cin >> a >> b >> c >> d){
            m = max(3*a/10,a-a*c/250);
            v = max(3*b/10,b-b*d/250);
            if(m>v)
                printf("Misha\n");
            else if(v>m)
                printf("Vasya\n");
            else printf("Tie\n");
        }
        return 0;
    }


B. Misha and Changing Handles

题目大意:
        改名字,只有没用过的新名字才可以改,可以改多次。找出最少改了一次的人的最开始的名字和最后改好的名字。

思路:
        首先判断,每一次更改能否成功,把不能修改的记录去掉「状态置为false」。并把用过的名字记录对应到他们的id,这样后面方便查找。从1开始处理,找到一个名字,看他的新名字是否有更改记录,如果有继续向下查找,直到没有修改记录。在向下查找的过程中把用过记录删掉「即把状态置为false」。

代码:

    #include<iostream>
    #include<cstdio>
    #include<map>
    #include<string>
    #include<cstring>
    #include<utility>
    using namespace std;

    int q;
    struct Node{
        string old,news;
        bool is;
        Node(){old=""; news=""; is=true;}
    }req[1009];
    string old,news;

    map<string, int> used;
    map<string, string> ans;

    int main()
    {
    //    freopen("in.txt","r",stdin);
        while(cin >> q){
            for(int i=1; i<=q; ++i){
                cin >> old >> news;
                req[i].old=old;
                req[i].news=news;
                req[i].is = true;
            }
            used.clear();
            for(int i=1; i<=q; ++i){
                used[req[i].old]=i;
                if(used.count(req[i].news)==0){
                    used[req[i].news]=1009;
                }
                else{
                    req[i].is=false;
                }
            }
            ans.clear();
            for(int i=1; i<=q; ++i){
                if(req[i].is){
                    news = req[i].news;
                    while(used[news]<=q && used[news]>0 && req[used[news]].is){
                        req[used[news]].is= false;
                        news=req[used[news]].news;
                    }
                    ans[req[i].old]=news;
                }
            }
            cout << ans.size() << endl;
            for(map<string, string>::iterator it=ans.begin(); it!=ans.end(); ++it)
                cout << it->first << " " << it->second << endl;
        }

        return 0;
    }


C. Misha and Forest

题目大意:
        一个无环且没有平行边的图,统计每个节点的所连边的个数和节点编号的异或(XOR)和。根据每个节点的所连边的个数和节点编号的异或和,还原图。

思路:
        这个图就是树,所以从所连边数是1的节点开始入手,并把这个边从记录的信息中删除(两个点都要删除),即:degree要减1,s要异或这个节点的值。记录一下边的信息输出就可以了。由于数据量大,不建议用c++的输入输出。

代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    using namespace std;

    struct Node{
        int from;
        int deg;
        int s;
        Node(){from=0;deg=0; s=0;}
        inline bool operator < (const Node &a) const{
            if(deg!=a.deg)
                return deg<a.deg;
            else return s<a.s;
        }
    }info[(1<<16)+9];
    int n;

    vector<int> g[(1<<16)+9];
    int mp[(1<<16)+9];

    int main()
    {
    //    freopen("in.txt","r",stdin);
        while(scanf("%d", &n)!=EOF){
            for(int i=0; i<n; ++i)
                g[i].clear();

            for(int i=0,deg,s; i<n; ++i){
                scanf("%d %d", °, &s);
                info[i].from = i;
                info[i].deg = deg;
                info[i].s = s;
            }
            sort(info,info+n);
            for(int i=0; i<n; ++i){
                mp[info[i].from] = i;
            }
            int ans=0;
            bool flg=true;
            while(true){
                flg = true;
                for(int i=0; i<n; ++i){
                    if(info[i].deg == 1){
                        g[info[i].from].push_back(info[i].s);
                        info[i].deg = 0;
                        ans++;
                        int id = mp[info[i].s];
                        info[id].deg--;
                        info[id].s = info[id].s ^ info[i].from;
                        flg= false;
                    }
                }
                if(flg)
                    break;
            }
            printf("%d\n",ans);
            for(int i=0; i<n; ++i){
                for(int j=0; j<g[i].size(); ++j){
                    printf("%d %d\n",i,g[i][j]);
                }
            }
        }
        return 0;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值