0914测试【提高组】(系实验选拔考2)
第一题:
A: 最小比例
时间限制: 1 Sec 内存限制: 128 MB提交: 55 解决: 13
[提交][状态][讨论版]
题目描述
图中共有N个点的完全图,每条边都有权值,每个点也有权值。要求选出M个点和M-1条边,构成一棵树,使得:
即所有边的权值比所有点的权值之和的比率最小。
给定N和M,以及N个点的权值,和所有的边权,要求M个点的最小比率生成树。
输入
第一行包含两个整数N和M(2<=N<=15,2<=M<=N),表示点数和生成树的点数。
接下来一行N个整数,表示N个点的边权。
最后N行,每行N列,表示完全图中的边权。所有点权和边权都在[1,100]之间。
输出
输出最小比率生成树的M个点。当答案出现多种时,要求输出的第一个点的编号尽量小,第一个相同,则第二个点的编号尽量小,依次类推,中间用空格分开。编号从1开始。
样例输入
3 2
30 20 10
0 6 2
6 0 3
2 3 0
2 2
1 1
0 2
2 0
样例输出
1 3
1 2
提示
【样例解释1】
取1,3,号点。
【数据范围】
对于30%数据,N<=5。
来源
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 30 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 31 ll read(){ ll ans=0; char last=' ',ch=getchar(); 32 while(ch<'0' || ch>'9')last=ch,ch=getchar(); 33 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); 34 if(last=='-')ans=-ans; return ans; 35 } 36 //头文件 37 38 39 40 41 ld Min=1000000; 42 int n,m,nu,a[20],q[20],fa[20],Ans[20]; 43 struct node{ 44 int x,y,num; 45 }f[500]; 46 bool cmp(node a,node b){ 47 return a.num<b.num; 48 } 49 int getfa(int x){ 50 if(fa[x]!=x) fa[x] = getfa(fa[x]); 51 return fa[x]; 52 } 53 int same(int x,int y){ 54 return getfa(x)==getfa(y); 55 } 56 void merge(int x,int y) 57 { 58 int fax=getfa(x),fay=getfa(y); 59 fa[fax]=fay; 60 } 61 void work() 62 { 63 int first=0; 64 rep(i,1,n) 65 if (q[i]) first=i; 66 rep(i,1,n) fa[i]=i; 67 int st=m,ansP=0; 68 for (int i=1;i<=nu && st>1;i++) 69 { 70 int x=f[i].x,y=f[i].y; 71 if (q[x] && q[y]) 72 { 73 if(same(x,y)) continue; 74 else{ 75 merge(x,y); 76 st--; 77 ansP+=f[i].num; 78 } 79 } 80 } 81 int ansW=0; 82 rep(i,1,n) if (q[i]) ansW+=a[i]; 83 if (Min>((ld)ansP/(ld)ansW)) { 84 Min=((ld)ansP/(ld)ansW); 85 rep(i,1,n) Ans[i]=q[i]; 86 } 87 } 88 void dfs(int t) 89 { 90 if (t>n){ 91 int number=0; 92 rep(i,1,n) if (q[i]) number++; 93 if (number==m) work(); return; 94 } 95 q[t]=1; dfs(t+1); 96 q[t]=0; dfs(t+1); 97 } 98 int main() 99 { 100 n=read(); m=read(); nu=0; 101 rep(i,1,n) a[i]=read(); 102 rep(i,1,n) 103 rep(j,1,n) f[++nu].x=i,f[nu].y=j,f[nu].num=read(); 104 sort(f+1,f+nu+1,cmp); 105 dfs(1); 106 rep(i,1,n) 107 if (Ans[i]) { 108 if (m>1) { cout<<i<<" "; m--;} 109 else {cout<<i; return 0;} 110 } 111 return 0; 112 }
B: 软件公司
时间限制: 1 Sec 内存限制: 128 MB提交: 47 解决: 12
[提交][状态][讨论版]
题目描述
一家软件开发公司有两个项目,并且这两个项目都由相同数量的m个子项目组成,对于同一个项目,每个子项目都是相互独立且工作量相当的。由于时效性,两个项目必须同时被完成,如果其中一个完成的早了,那么这两个项目都会无效。
这家公司有n名程序员分配给这两个项目,每个子项目必须由一名程序员一次完成,多名程序员可以同时做同一个项目中的不同子项目。
求公司完成两个项目的最少时间。
输入
第一行两个正整数n,m(1<=n<=100,1<=m<=100)。
接下来n行,每行包含两个整数,x和y。分别表示每个程序员完成第一个项目的子程序的时间,和完成第二个项目子程序的时间。每个子程序耗时也不超过100。
输出
包含一个整数,表示两个项目同时完成的时间。
样例输入
3 20
1 1
2 4
1 6
样例输出
18
提示
【样例解释】
第一个人做18个2项目,耗时18;第二个人做2个1项目,2个2项目耗时12;第三个人做18个1项目,耗时18。
【数据范围】
对于30%的数据,n<=30.
对于60%的数据,n<=60.
来源
这题不用多说就知道是DP了,那这题怎么写呢?
先看30%的数据:
dp[i][x][y]表示到第i个人,第一个项目完成x个,第二个项目完成y个的最小时间,
dp[i][x][y]=min(dp[i][x][y],max(dp[i][x-i_][y-j_],i_*a[i]+j_*b[i]))
耗时:n*m^4; PS:OJ跑的快过了50%,
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 30 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 31 ll read(){ ll ans=0; char last=' ',ch=getchar(); 32 while(ch<'0' || ch>'9')last=ch,ch=getchar(); 33 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); 34 if(last=='-')ans=-ans; return ans; 35 } 36 int a[200],b[200],dp[105][105][105]; 37 int main() 38 { 39 int n=read(),m=read(); 40 rep(i,1,n) a[i]=read(),b[i]=read(); 41 rep(i,0,n) 42 rep(x,0,m) 43 rep(y,0,m) 44 dp[i][x][y]=1e+8; 45 dp[0][0][0]=0; 46 rep(i,1,n) 47 rep(x,0,m) 48 rep(y,0,m) 49 rep(i_,0,x) 50 rep(j_,0,y) 51 dp[i][x][y]=min(dp[i][x][y],max(dp[i-1][x-i_][y-j_],i_*a[i]+j_*b[i])); 52 cout<<dp[n][m][m]; 53 }
在看60%的数据:
这题有明显的二分性,所以枚举答案,在可以算出j_;
而dp表示能不能取到。耗时:log(m)*n*m^3;PS:OJ跑的还要快,就A了;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 30 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 31 ll read(){ ll ans=0; char last=' ',ch=getchar(); 32 while(ch<'0' || ch>'9')last=ch,ch=getchar(); 33 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); 34 if(last=='-')ans=-ans; return ans; 35 } 36 int a[200],b[200],dp[105][105][105]; 37 int main() 38 { 39 int n=read(),m=read(); 40 rep(i,1,n) a[i]=read(),b[i]=read(); 41 int r=1,l=100; 42 while (r<l){ 43 int mid=(r+l)/2; 44 rep(i,0,n) 45 rep(x,0,m) 46 rep(y,0,m) 47 dp[i][x][y]=0; 48 dp[0][0][0]=1; 49 rep(i,1,n) 50 rep(x,0,m) 51 rep(y,0,m){ 52 for (int i_=0;i_<=x && i_*a[i]<=mid;i_++){ 53 int j_=(mid-i_*a[i])/b[i]; 54 if (j_>=0) dp[i][x][y]=dp[i][x][y]|dp[i-1][x-i_][max(0,y-j_)]; 55 } 56 } 57 if (dp[n][m][m]) l=mid; 58 else r=mid+1; 59 } 60 cout<<r; 61 }
不感觉TMD表示能不能取到很浪费吗!
于是乎,可以把一位y放进去,dp表示成能去到的y的最小值,
耗时:log(m)*n*m^2。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 30 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 31 ll read(){ ll ans=0; char last=' ',ch=getchar(); 32 while(ch<'0' || ch>'9')last=ch,ch=getchar(); 33 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); 34 if(last=='-')ans=-ans; return ans; 35 } 36 int a[200],b[200],dp[105][105]; 37 int main() 38 { 39 int n=read(),m=read(); 40 rep(i,1,n) a[i]=read(),b[i]=read(); 41 int r=1,l=100; 42 while (r<l){ 43 int mid=(r+l)/2; 44 rep(i,0,n) 45 rep(x,0,m) 46 dp[i][x]=-1e+8; 47 dp[0][0]=0; 48 rep(i,1,n) 49 rep(x,0,m) 50 for (int i_=0;i_<=x && i_*a[i]<=mid;i_++){ 51 int j_=(mid-i_*a[i])/b[i]; 52 if (j_>=0) dp[i][x]=max(dp[i][x],dp[i-1][x-i_]+j_); 53 } 54 if (dp[n][m]>=m) l=mid; 55 else r=mid+1; 56 } 57 cout<<r; 58 }
2162: 摧毁巴士站
时间限制: 1 Sec 内存限制: 128 MB提交: 25 解决: 3
[提交][状态][讨论版]
题目描述
Gabiluso是最伟大的间谍之一。现在,他试图完成一个“不可能完成”的使命――减缓Colugu的军队到达机场的时间。Colugu有n个公共汽车站和m条道路。每条道路直接连接两个巴士站,所有的道路都是单向的。为了保持空气洁净,政府禁止所有军用车辆,因此,军队必须乘搭巴士去机场。两个巴士站之间,可能有超过一条道路。如果一个公共汽车站被破坏时,所有连接该站的道路将无法运作。Gabiluso需要做的是摧毁了一些公共汽车站,使军队无法在K分钟内到达机场。一辆公交车通过一条道路,都是一分钟。所有巴士站的编号从1到n。1号巴士站是在军营,第n号站是机场。军队始终从第一站出发。第一站和第n站不能被破坏,这里有大量的防御力量。当然也没有从第一站到第n站的道路。
请帮助Gabiluso来计算能完成使命所需摧毁的最低数目的巴士站。
输入
第一行包含三个整数n,m,k (2<n<=50,0<m<=4000,0<k<1000)。
接下来m行,每行2个整数s和f,表示从站s到站f有一条路。
输出
输出最少需要摧毁的巴士站数目。
样例输入
5 7 3
1 3
3 4
4 5
1 2
2 5
1 4
4 5
样例输出
2
提示
来源
PS:暴力懒得打了,网络流不会。