Swust 2019级第3次周赛

图论

(菜的扣jio 啥也不会)

 

 

 

题目分析:

A 签到题 注意向上取整

 

题面

sy总是喜欢做一些非常没有意义的事情,比如和Mannix比赛短跑。 众所周知Mannix是短跑冠军,所以他准备先让sy跑一会儿,但是此时会发生一些比较尴尬的事情,比如装B失败输掉了比赛。sy想知道Mannix装多大的B才能不输给Mannix,你能帮帮他吗? 假定现在Mannix跑完整个赛道的时间为z,Mannix的速度为x,sy的速度为y,请你帮sy计算出Mannix最少可以让sy多少秒,以至于sy可以赢Mannix或和Mannix打平?

Input

输入一行包括三个整数x,y,z(1≤x,y,z≤1000,x>y)

Output

输出一行一个整数表示答案

 

Examples

Input
4 1 1

Output
3

 

 (x/y 向上取整    (x+y-1)/y

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<cstdio>
#include<queue>
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1000000;
const int inf = 0x3f3f3f3f;
using namespace std;
int main()
{
     ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int x,y,z;
    cin>>x>>y>>z;
    int ans = 0;
    
    if((z*x)%y==0)
    {
        ans = ( z * x / y ) - z;
    }
    else
    {
        ans = ( z * x / y ) - z + 1 ;
    }
    cout<< ans <<endl;
    
     
    
}
View Code

 

 

 

 

C SPFA判断负环板子

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<cstdio>
#include<queue>
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1000000;
const int inf = 0x3f3f3f3f;
using namespace std;
/*SPFA判断是否存在负环*/
struct node
{
    int u,v,w,next;
}e[10050];

int dis[10050],head[10050],cnt;
bool vis[10050];
int num[10050];//记录入队次数 
int n,m,w; 
void add(int u,int v,int w)
{
    e[cnt].u = u;
    e[cnt].v = v;
    e[cnt].w = w;
    e[cnt].next = head[u];
    head[u] = cnt++;
}
bool spfa()
{
    memset(vis,0,sizeof(vis));
    memset(num,0,sizeof(num));
    memset(dis,inf,sizeof(dis));
    queue<int> q;
    dis[1]=0;
    q.push(1);
    num[1]++;
    while(!q.empty())
    {
        int x = q.front();
        q.pop();
        vis[x]=0;
        for(int i = head[x];~i;i=e[i].next)
        {
            int v = e[i].v;
            if(dis[v]>dis[x]+e[i].w)
            {
                dis[v] = dis[x] + e[i].w;
                if(!vis[v])
                {
                    vis[v]=1;
                    num[v]++;
                    q.push(v);
                    if(num[v]>=n)
                    {
                        return true;
                    }
                } 
            }
        }
    }
    return false;
}
int main()
{
     ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        cnt = 0;
        memset(head,-1,sizeof(head));
        scanf("%d %d %d",&n,&m,&w);
        for(int i=0;i<m;i++)
        {
            int u,v,s;
            cin>>u>>v>>s;
            add(u,v,s);
            add(v,u,s);
        }
        for(int i=0;i<w;i++)
        {
            int u,v,s;
            cin>>u>>v>>s;
            add(u,v,-s);
        }
        if(spfa())
        {
            cout<<"YES"<<endl;
        }
        else
        {
            cout<<"NO"<<endl;
        }
    }
}
View Code

 

 

 

D 判断MST是否唯一    参考:https://blog.csdn.net/no_retreats/article/details/8159680

 

#include<iostream>
using namespace std;
#include<algorithm>
#define MAXN 105
int parent[MAXN],n,m;
struct node
{
    int u,v,w;
    int equal;//改变是否唯一 是为0 否为1
    int use;//改变是否使用,是为1 否为0
    int del;//改变是否被删除 是为1 否为0
}map[10000];
bool first;//记录是第一次就是MST中的边
void UFset()
{
    for(int i=0;i<n;i++)
        parent[i]=-1;
}
int Find(int x)
{
    int s,tmp;
    for(s=x;parent[s]>=0;s=parent[s]);
    while(s!=x)
    {
        tmp=parent[x];
        parent[x]=s;
        x=tmp;
    }
    return s;
}
void Union(int R1,int R2)
{
    int r1=Find(R1),r2=Find(R2);
    int tmp=parent[r1]+parent[r2];
    if(parent[r1]>parent[r2])
    {
        parent[r1]=r2;
        parent[r2]=tmp;
    }
    else
    {
        parent[r2]=r1;
        parent[r1]=tmp;
    }
}
bool cmp(node a,node b)
{
    return a.w<b.w;
}
int Kruskal()
{
    int sum=0;
    int num=0;
    int u,v,i;
    UFset();
    for(i=0;i<m;i++)
    {
        if(map[i].del==1)//如果该边是被删除的了,那就不处理
            continue;
        u=map[i].u,v=map[i].v;
        if(Find(u)!=Find(v))
        {
            sum+=map[i].w;
            if(first)    
                map[i].use=1;//记录该边已经在MST中了
            Union(u,v);
            num++;
        }
        if(num>n)
            break;
    }
    return sum;
}
int main()
{
    int T,i,a,b,c;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        for(i=0;i<m;i++)
        {
            cin>>a>>b>>c;
            map[i].u=a-1;map[i].v=b-1;map[i].w=c;
            map[i].equal=map[i].use=map[i].del=0;//初始化
        }
        for(i=0;i<m;i++)//标记权值相同的边
        {
            for(int k=0;k<m;k++)
            {
                if(i==k)
                    continue;
                if(map[i].w==map[k].w)
                    map[i].equal=1;
            }
        }
        sort(map,map+m,cmp);
        first=true;
        int weight1=Kruskal(),weight2;//第一次求MST
        first=false;
        int j;
        for( j=0;j<m;j++)//依次删除相同的权值的边并进行MST的求解
        {
            if(map[j].use&&map[j].equal)
            {
                map[j].del=1;
                weight2=Kruskal();
                if(weight1==weight2)
                {
                    cout<<"Not Unique!"<<endl;
                    break;
                }
                map[j].del=0;
            }
            
        }
        if(j>=m)
            cout<<weight1<<endl;
    }
    return 0;
}
 
 
 
View Code

 

 

 

 

E题 正反建图

题面:

炎龙侠在为他的科幻小说小说中的世界,设计一幅交通图。
大部分行星之间都建有传送门,但是传送门只能单向通过,而且,因为技术条件的差异,以及设备的老化,每个传送门,传送需要的时间基本都不相同。
他在小说中设计了一个情节,主角梅川瓦子得到了情报,有外星人要同时对她所在势力的n颗行星发动攻击,她在编号为1的行星上。
由于超距通讯系统的损坏,她只能派出一架无人机,穿过传送门,前去通知编号2~n的行星。
有关外星人的资料很多,无人机的存储器无法存下,于是她准备了n-1块硬盘。无人机每次可以携带一块硬盘(根据sy的建议,硬盘应该绑在无人机的腿上),前去通知完一颗行星后,它要回到梅川瓦子身边,再带上新的硬盘,通知下一个行星
时间紧迫,梅川瓦子希望你能帮帮她计算一下,无人机前去通知n-1颗行星,再回到它身边,所花费的最短时间的总和

Input

输入由T个案例组成。输入的第一行只包含正整数T。
接下来是N和M,1 <= N,M <= 1000000,表示N个行星和连接N个行星的M个单向传送门。
然后有M行,每行包括三个值U,V,W,表示从行星U到行星V的传送门,传送需要的时间W。

Output

对于每个案例,打印一行,表示花费时间总和的最小值。

Sample Input

2
2 2
1 2 6
2 1 4
3 5
1 2 8
2 1 16
1 3 50
2 3 41
3 2 47

Sample Output

10
136

Hints

注意不要使用万能头文件,不要使用cin和cout

 

 

#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<cstdio>
#include<queue>
#include<stdio.h>
#include<iostream>
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 10000100;
const int inf = 0x3f3f3f3f;
using namespace std;
/*dij堆优化*/ 
struct edge
{
    int to, dis, next;   
};

edge e[maxn] = {0,0,0};

int head[maxn], dis[maxn], cnt;

bool vis[maxn];

int n, m, s;

inline void add_edge( int u, int v, int d )
{
    cnt++;
    e[cnt].dis = d;
    e[cnt].to = v;
    e[cnt].next = head[u];
    head[u] = cnt;
}
struct node
{
    
    int dis;
    int pos;
    bool operator < ( const node &x )const
    {
        return x.dis < dis;
    }
    
};

priority_queue<node> q;

void init()
{
    cnt = 0;
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(dis,inf,sizeof(dis));
    memset(e,0,sizeof(e));
}

inline void dijkstra(int start)
{
    dis[start] = 0;
    
    q.push( ( node ){0, start} );
    while( !q.empty() )
    {
        node tmp = q.top();
        
        q.pop();
        
        int x = tmp.pos ; 
        
        if(vis[x])
        continue;
        
        vis[x] = 1;
        
        for( int i = head[x]; i; i = e[i].next )
        {
            int y = e[i].to;
            
            if( dis[y] > dis[x] + e[i].dis )
            {
                dis[y] = dis[x] + e[i].dis;
                if( !vis[y] )
                {
                    q.push( ( node ){dis[y], y} );
                }
            }
        }
    }
}
int main()
{
    int t;
    
    scanf("%d",&t);
    while(t--) 
{
    scanf("%d %d",&n,&m);
    
    init();
    
    ll ans = 0;
    
    for( register int i = 1; i <=m; ++i )
    {
        
        register int u, v, d;
        scanf("%d %d %d",&u,&v,&d);        // u起点 v终点 d权重 
        add_edge( u, v, d );
        add_edge(v+n,u+n,d);
    } 
    dijkstra(1);
    
    for(int i=2;i<=n;++i)
    {
        ans+=dis[i];
    }
    
    dijkstra(1+n);
    
    for(int i = 2+n;i<=n<<1;++i)
    {
        ans+=dis[i];
    }
    printf("%lld\n",ans);
    
}
    
}
    
View Code

 

 

 F 贪心 CodeForces 371C 

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<cstdio>
#include<queue>
#define int long long
const int manx = 2e6 + 10;
const int INF = 1e18;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1000000;
const int inf = 0x3f3f3f3f;
using namespace std;

char str[200];
int b=0,s=0,c=0,n1,n2,n3,p1,p2,p3,r;
int check()
{
    int temp=0;
    n1-=b,n2-=s,n3-=c;
    if(n1<0)temp-=n1*p1;
    if(n2<0)temp-=n2*p2;
    if(n3<0)temp-=n3*p3;
    n1=max(n1,0ll);
    n2=max(n2,0ll);
    n3=max(n3,0ll);
    return temp;
}
signed main()
{
    cin>>str;
    for(int i=0;str[i]!='\0';i++)
    {
        if(str[i]=='B')b++;
        else if(str[i]=='S')s++;
        else c++;
    }
    cin>>n1>>n2>>n3;
    cin>>p1>>p2>>p3;
    cin>>r;
    int ans=0,cou=-1;
    if(b)cou=max(n1/b,cou);
    if(s)cou=max(n2/s,cou);
    if(c)cou=max(n3/c,cou);
    while(cou--)
    {
        int temp=check();
        if(temp<=r)
        {
            r-=temp;
            ans++;
        }
        else break;
    }
    int temp=check();
    if(temp<=r)
    {
        r-=temp;
        ans++;
    }
    ans+=r/(b*p1+s*p2+c*p3);
    cout<<ans<<endl;
    return 0;
}
View Code

 

 

 

 

posted @ 2020-08-02 16:36  Wh1te  阅读(122)  评论(0编辑  收藏  举报