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
4 1 1
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; }
B
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; } } }
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; }
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); } }
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; }