10.14上午

T1 P2619 [国家集训队]Tree I

Sol
题目实际上的意思就是把原来的最小生成树加上了一个黑白边限制。为了保证我们的答案在符合要求的同时能够最优,用\(Kruskal\)算法的思想:把全局的边排序求解。那么为了满足要求我们考虑对白色边的权值进行统一修改,使得黑白边顺序在保证正确性的前提下重新排序。这个修改值用二分确定,最后答案除去修改的值即可。
Code

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
    return f?x:-x;
}
const int maxn=100010;
int n,m,lim,ans;
struct edge
{
    int to,next,from,v,cl;
}e[maxn<<1];
int h[maxn],ei;
inline void add(int x,int y,int v,int c)
{
    e[++ei]=(edge){y,h[x],x,v,c};
    h[x]=ei;return;
}
struct node
{
    int cl,len,u,v;
    bool operator<(const node &x)const
    {
        if(len==x.len)return cl>x.cl;
        return len>x.len;
    }
};
priority_queue<node>qu;
int fa[maxn];
inline int findf(int x)
{
    if(fa[x]==x)return x;
    return fa[x]=findf(fa[x]);
}
inline int klskr(int mj)
{
    ans=0;
    for(int i=1;i<=n;i++)fa[i]=i;
    while(!qu.empty())qu.pop();
    for(int i=1;i<=ei;i++)
    {
        qu.push((node){e[i].cl,e[i].v+(e[i].cl==0?mj:0),e[i].from,e[i].to});
    }
    int now=0,cnt=0;
    while(!qu.empty())
    {
        node x=qu.top();qu.pop();
        int fu=findf(x.u),fv=findf(x.v);
        if(fu==fv)continue;
        ans+=x.len;now++;cnt+=((x.cl)^1);
        fa[fv]=fu;
        if(now==n-1)break;
    }
    ans-=lim*mj;
    return cnt;
}
int main()
{
    freopen("e.in","r",stdin);
    freopen("e.out","w",stdout);
    n=read();m=read();lim=read();
    for(int i=1;i<=m;i++)
    {
        int x=read()+1,y=read()+1,z=read(),w=read();
        add(x,y,z,w);
    }
    int l=-1000,r=1000;
    while(l<r)
    {
        int mid=(l+r)>>1;
        int nn=klskr(mid);
        if(nn>lim)l=mid+1;
        else r=mid;
    }
    klskr(l-1);
    printf("%d\n",ans);
    return 0;
}

T2 P1129 [ZJOI2007] 矩阵游戏

Sol
降智了。显然换行不换列,换列不换行。所以可以以行和列建二分图,矩阵中为1的点就把它对应的行和列建边。跑一边二分图最大匹配,满配则可行,否则不行。
Code
略了。

T3 贪吃蛇

Sol
A*,不会。

T4 信息拦截

Sol
先跑一遍缩点,所有连通块大小大于等于2的都不行,缩完以后剩下一个DAG,从1跑一遍拓扑,然后从n跑一遍反图拓扑,去掉访问不到的点。剩下的点里面求割点即可。可以建成无向图跑tarjan,也可以先给每个点一个拓扑序,然后再用拓扑优先队列bfs,当取出该点后队列为空则为割点。
Code
working on it……

posted @ 2021-10-14 20:31  wwlvv  阅读(25)  评论(0)    收藏  举报