2017 Multi-University Training Contest

来源:互联网 发布:淘宝我的购物车打不开 编辑:程序博客网 时间:2024/06/10 10:11

这虽然不是我发挥最好的一场比赛,但是是我最开心也是我最满意的一场比赛。终于感受到了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;}