2017 Multi-University Training Contest - Team 10

这虽然不是我发挥最好的一场比赛,但是是我最开心也是我最满意的一场比赛。终于感受到了ACM3人是一个团队的美妙的感觉和合作的开心。


1008(dp+fastinput)

In this problem, we must remove edges as many as possible and assign each of the K monkeys to the vertices so that all the monkeys are directly connected to at least one another monkey by the remaining edges. So, we must work out the maximum bipartite matching of all the vertices first. Let’s denote the size of maximum bipartite matching S. Then, we can choose T= min(K / 2, S) pairs of matched vertices and assign 2 * T monkeys to that vertices and assign all the other monkeys to the remaining vertices which are directly connected to already occupied vertices. Hence, the optimal answer is T + (K – 2 * T) = K - T.

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;


const int N = 100000;
int f[N + 10];
int fa[N + 10];
int g[N + 10];
int n, m, k, i, T, x, y, tmp;


const int BUFSIZE= 100000000;
char Buf[BUFSIZE+1],*buf=Buf;
template<class T>


void scan(T&a){
for(a=0;*buf<'0'||*buf>'9';buf++);
while(*buf>='0'&&*buf<='9'){a=a*10+(*buf-'0');buf++;}}


int main() {
    fread(Buf,1,BUFSIZE,stdin);
    scan(T);
    while (T--) {
        scan(n); scan(m);
        for (i = 2; i <= n; ++i) {
            scan(fa[i]);
        }


        memset(f, 0, sizeof(f));
        memset(g, 0, sizeof(g));
        for (i = n; i >= 2; --i) {
            f[fa[i]] += max(f[i], g[i]);
            f[fa[i]] = max(f[fa[i]], 1 + g[i] + g[fa[i]]);
            g[fa[i]] += max(f[i], g[i]);
        }
        tmp = max(f[1], g[1]);
        x = m / 2;
        x = min(tmp, x);
        y = m - x * 2;
        tmp = x + y;
        printf("%d\n", tmp);
    }
    return 0;
}

1010

In this problem, we must assign each task in optimal way so that minimize the number of working machines first and when we use minimum number of machines, also minimize the total working time of all machines. So, we can use greedy method to solve this problem. First, we must sort all the tasks in increasing order of their starting time. Then, selecting the tasks in that order, we must choose the machine which is available to assign current task and most recently finished its working, and assign current task to that machine. When there isn’t such machine, we must assign current task to a new machine. By doing so, we can minimize both the number of working machine and total working time.

#include <bits/stdc++.h>


#define mp make_pair


using namespace std;
typedef long long ll;
const int maxn = 100000 + 5;


struct node{
int l,r;
}info[maxn];


multiset<pair<int,int> > S;


bool cmp(node A,node B){
if(A.l == B.l)
return A.r<B.r;
return A.l<B.l; 



int main(){
int T,n;
cin>>T;
while(T--){
S.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&info[i].l,&info[i].r);
}
sort(info+1,info+1+n,cmp);
for(int i=1;i<=n;i++){
auto it = S.lower_bound(mp(info[i].l,-1));
if(it!=S.end()){
if((it->first) > info[i].l){
if(it!=S.begin()){
it--;
S.insert(mp(info[i].r,it->second));
S.erase(it);
} else S.insert(mp(info[i].r,info[i].l));
} else {
S.insert(mp(info[i].r,it->second));
S.erase(it);
}
} else if(it!=S.begin()){
it--;
S.insert(mp(info[i].r,it->second));
S.erase(it);
} else {
S.insert(mp(info[i].r,info[i].l));
}
}
ll res = 0;
for(auto it = S.begin();it!=S.end();it++){
res += (it->first) - (it->second);
}
printf("%d %lld\n",S.size(),res);
}
return 0;


T1011 (次短路模板+改输入输出)



#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, int> P;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 7;

struct Edge{
    int to;
    LL cost;
    Edge(int tv = 0, LL tc = 0):to(tv), cost(tc){}
};
vector<Edge> G[N];
int n, m;
LL dist[N];     //最短距离
LL dist2[N];    //次短距离

LL Dijkstra(){
    memset(dist, INF, sizeof(dist));
    memset(dist2, INF, sizeof(dist2));
    //从小到大的优先队列
    //使用pair而不用edge结构体
    //是因为这样我们不需要重载运算符
    //pair是以first为主关键字进行排序
    priority_queue<P, vector<P>, greater<P> > Q;
    //初始化源点信息
    dist[1] = 0;
    Q.push(P(0, 1));
    //同时求解最短路和次短路
    for(; !Q.empty();){
        P p = Q.top(); Q.pop();
        //first为s->to的距离,second为edge结构体的to
        int v = p.second;
        LL d = p.first;
        //当取出的值不是当前最短距离或次短距离,就舍弃他
        if (dist2[v] < d) continue;
        for (int i = 0; i < G[v].size(); i++){
            Edge &e = G[v][i];
            LL d2 = d + e.cost;
            if (dist[e.to] > d2){
                swap(dist[e.to], d2);
                Q.push(P(dist[e.to], e.to));
            }
            //printf("dist2[%d] = %d, d2 = %d\n", e.to, dist2[e.to], d2);
            if (dist2[e.to] > d2 && dist[v] < d2){
                dist2[e.to] = d2;
                Q.push(P(dist2[e.to], e.to));
            }
        }
    }
    return dist2[n];
}

int main(){
    int T, u, v;
    LL w;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        for (int i = 0; i <= n; i++) G[i].clear();
        for (int i = 0; i < m; i++){
            scanf("%d%d%lld", &u, &v, &w);
            G[u].push_back(Edge(v, w));
            G[v].push_back(Edge(u, w));
        }
        printf("%lld\n", Dijkstra());
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值