SDUT 2022 Summer Individual Contest - 6 (补题)

题目链接:

Brexit - Kattis brexit - Virtual Judge (vjudge.net)

题意:给出c,p,x,l代表给出c个部落,有p个联盟关系,x代表目标部落,l是最先脱离的部落。接下来有p行,每行输入a,b代表a,b有联盟关系;
部落脱离部条件是建立联盟的伙伴>=一半的脱离。
询问:x最后如果能脱离联盟输出leave,否则输出stay;

分析:链式前向星+bfs或vector+bfs跑一遍就可以

链式前向星+bfs:

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
#define PI acos(-1)
#define SugarT ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=2e5+10;
const int M=1e6+10;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const double eps = 1e-6;

int c,p,x,l;
int h[N],e[M],ne[M],idx;
int cnt[N],now[N];
bool st[N];

void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void solve()
{

    memset(h,-1,sizeof h);
    cin >> c >> p >> x >> l;
    while(p--)
    {
        int a,b;
        cin >> a >> b;
        add(a,b);
        add(b,a);
        cnt[a]++,cnt[b]++;//记录每个国家的贸易国总数
        now[a]++,now[b]++;//记录每个国家现存的贸易国数量
    }
    queue<int> q;
    q.push(l);
    while(q.size())
    {
        auto t=q.front();
        q.pop();
        if(st[t])continue;
        st[t]=true;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            auto j=e[i];
            if(st[j])continue;//如果已经被标记过就往下找
            now[j]--;
            if(now[j]*2<=cnt[j])q.push(j);//判断这个国家是否需要退出
        }
    }
    if(!st[x])cout << "stay" << endl;
    else cout << "leave" << endl;

}

int main()
{
    SugarT
    int T=1;
        //cin >> T;
    while(T--)
        solve();

    return 0;
}

vector+bfs:

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
#define PI acos(-1)
#define SugarT ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=2e5+10;
const int M=1e6+10;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const double eps = 1e-6;

int c,p,x,l;
vector<int> v[N];
int cnt[N],now[N];
bool st[N];

void solve()
{

    cin >> c >> p >> x >> l;
    while(p--)
    {
        int a,b;
        cin >> a >> b;
        v[a].push_back(b);
        v[b].push_back(a);
        cnt[a]++,cnt[b]++;//记录每个国家的贸易国总数
        now[a]++,now[b]++;//记录每个国家现存的贸易国数量
    }
    queue<int> q;
    q.push(l);
    while(q.size())
    {
        auto t=q.front();
        q.pop();
        if(st[t])continue;
        st[t]=true;
        for(int i=0;i<v[t].size();i++)
            if(st[v[t][i]])continue;//如果已经被标记过就往下找
            else{
                now[v[t][i]]--;
                if(now[v[t][i]]*2<=cnt[v[t][i]])//判断这个国家是否需要退出
                    q.push(v[t][i]);
            }
    }
    if(!st[x])cout << "stay" << endl;
    else cout << "leave" << endl;

}

int main()
{
    SugarT
    int T=1;
        //cin >> T;
    while(T--)
        solve();

    return 0;
}

题目链接:

Charles in Charge - Kattis

题意:一张城市网,有n个城市,m条高速公路,只有城里有充电站、公路上没有充电站,充电时间不计,汽车电池有多少电量就只能走多少路,男人每天需要在1号家和m好公司之间奔波,男人为了省钱需要买尽可能小的汽车电池,女人为了让男人尽快的回家让男人走最近的路。经过妥协,男人必须走不超过最短路长度x%的路,在这基础上男人能买的最小电池为多少?

分析:跑一遍Dijkstra将最短距离算出来,所以题目要求的最短路的长度不能超过(1+%x)*dist[n],所以二分电瓶容量,电瓶容量=最短路中道路最大的权值,所以当电瓶容量为x时,图里面权值大于x的边可以不用进行考虑。

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
#define int long long 
#define PI acos(-1)
#define SugarT ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=1e5+10;
const int M=1e6+10;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const double eps = 1e-6;

int n,m,x;
int h[N],e[M],ne[M],w[M],idx;
int dist[N];
bool st[N];

struct node
{
    int x;
    int y;
};

struct cmp
{
    bool operator() (const node &a,const node &b) const
    {
        return a.x>b.x;
    }
};

void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}

int Dijkstra(int maxv)//maxv为允许出现的最大边长权值
{
    memset(dist,0x3f,sizeof dist);
    memset(st,false,sizeof st);
    dist[1]=0;
    priority_queue<node,vector<node>,cmp> q;
    q.push({0,1});
    while(q.size())
    {
        auto t=q.top();
        q.pop();
        int dis=t.x,ver=t.y;
        if(st[ver])continue;
        st[ver]=true;
        for(int i=h[ver];i!=-1;i=ne[i])
        {
            auto j=e[i];
            if(w[i]<=maxv)//只有小于限定权值大小的边才能进行迭代
            {
                if(dist[j]>dist[ver]+w[i])
                {
                    dist[j]=dist[ver]+w[i];
                    q.push({dist[j],j});
                }
            }
        }
    }
    return dist[n];
}

void solve()
{

    memset(h,-1,sizeof h);
    int maxs=-1;
    cin >> n >> m >> x;
    while(m--)
    {
        int a,b,c;
        cin >> a >> b >> c;
        maxs=max(maxs,c);
        add(a,b,c);
        add(b,a,c);
    }
    int res=Dijkstra(INF);
    double sum=res*1.0*(1.0+x*1.0/100);//允许出现的最短路最大值
    //cout << sum << endl;
    int l=0,r=maxs;
    while(l<r)
    {
        int mid=l+r>>1;
        if(Dijkstra(mid)*1.0>sum)l=mid+1;
        else if(Dijkstra(mid)*1.0<sum)r=mid;
        else 
        {
            cout << mid << endl;
            return;
        }
    }
    cout << l << endl;
}

signed main()
{
    SugarT
    int T=1;
        //cin >> T;
    while(T--)
        solve();

    return 0;
}

 

posted @ 2022-07-11 20:35  MrSugarT  阅读(24)  评论(0编辑  收藏  举报