http://acm.csu.edu.cn/OnlineJudge/contest.php?cid=2036
A:
法一:
p = 0.a1a2a3...ak(b1b2...bm)
A = p*10^k = a1a2a3...ak.(b1b2...bm)
B = p*10^(k+m) = a1a2a3...akb1b2...bm.(b1b2...bm)
于是得B-A = p(10^(k+m)-10^(k))为整数
p = (B-A)/(10^(k+m)-10^(k));
直接辗转相除 化为最简形式
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #define LL long long #define max(a,b)a>b?a:b #define min(a,b)a<b?a:b #define maxn 100000 #define maxm 100000 #define inf 999999 using namespace std; char s[100]; char a[100]; char b[100]; LL gcd(LL m,LL n) { return m%n==0?n:gcd(n,m%n); } int main() { while(scanf("%s",s)!=-1) { int len = strlen(s); int k1; int k2; k1 = k2 = 0; for(int i=2;i<len && s[i]!='(';i++) a[k1++] = s[i]; a[k1] = 0; for(int i=k1+3;i<len && s[i]!=')';i++) b[k2++] = s[i]; b[k2] = 0; bool flag = 1; for(int i=0;i<k2;i++) { if(b[i]!='0'){ flag = 0; break; } } if(flag){ LL m = 1; LL ans = 0; for(int i=k1-1;i>=0;i--) { ans += m*(a[i]-48); m *= 10; } LL c = gcd(ans,m); printf("%lld/%lld\n",ans/c,m/c); continue; } LL m1 = 1; LL A = 0; for(int i=k1-1;i>=0;i--) { A += m1*(a[i]-48); m1*=10; } LL B = 0; LL m2 = 1; for(int i=k2-1;i>=0;i--) { B += m2*(b[i]-48); m2 *= 10; } for(int i=k1-1;i>=0;i--) { B += m2*(a[i]-48); m2*=10; } LL s = gcd(B-A,m2-m1); printf("%lld/%lld\n",(B-A)/s,(m2-m1)/s); } return 0; }
法二:
根据 0.(9)=1,按人工模拟的方法把小数化成分数,再化成最简分数.
#include"stdio.h" #include"string.h" #include"math.h" char ch[20]; long long work(long long m,long long n) { long long r; r=m%n; while(r!=0) { m=n; n=r; r=m%n; } return n; } int main() { long long x,y,x1,y1; long long xx,yy; int i,j,l; while(scanf("%s",ch)!=EOF) { l=strlen(ch); int find=0; for(i=0; i<l; i++) { if(!(ch[i]=='0'||ch[i]=='.'||ch[i]=='('||ch[i]==')')) { find=1; break; } } if(find==0) { printf("0/1\n"); continue; } int sum1,sum2; sum1=sum2=0; for(i=0; i<l; i++) { if(ch[i]=='.') continue; else if(ch[i]!='(') { sum1++; } else break; } sum2=l-sum1-3; xx=yy=0; for(i=sum1,j=1; i>=0; i--) { if(ch[i]=='.') continue; xx+=(int)(ch[i]-'0')*j; j*=10; } for(i=l-2,j=1; i>=0; i--,j*=10) { if(ch[i]=='(') break; yy+=(int)(ch[i]-'0')*j; } x1=pow(10,sum2)-1; i=0; while(ch[i]!='.'||ch[i]=='0') i++; y1=pow(10,sum1-i); if(yy==0) { x=xx; y=y1; } else { x=yy+xx*x1; y=x1*y1; } long long m,n; m=x; n=y; long long e; while(work(m,n)!=1) { e=work(m,n); m=m/e; n=n/e; } printf("%lld/%lld\n",m,n); getchar(); } return 0; } /************************************************************** Problem: 1303 User: wanglong306 Language: C++ Result: Accepted Time:0 ms Memory:980 kb ****************************************************************/
B Manor:
【模拟】时间O(M*N)。无压力。注意,求第m次操作前前前前的B中元素个数。
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #define maxn 100010 5 6 int n,m,a,b; 7 int seq[maxn]; 8 int q; 9 10 int ans[222]; 11 int main() 12 { 13 while (scanf("%d%d%d%d",&n,&m,&a,&b)==4) 14 { 15 int mm = 0; 16 int pos = 0; 17 ans[0] = 0; 18 for (int i=1;i<=n;i++){ 19 scanf("%d",&seq[i]); 20 if (seq[i] > mm) 21 { 22 mm = seq[i]; 23 pos = i; 24 } 25 if (seq[i] > m) 26 { 27 ans[0]++; 28 } 29 } 30 31 for (int i=1;i<=200;i++) 32 { 33 if (mm > m) 34 { 35 seq[pos] = 0; 36 } 37 ans[i] = 0; 38 mm = 0; 39 pos = 0; 40 for (int j=1;j<=n;j++) 41 { 42 if (seq[j]<=m){ 43 seq[j] += a; 44 }else{ 45 seq[j] += b; 46 } 47 48 if (seq[j] > m) 49 { 50 ans[i]++; 51 } 52 if (seq[j] > mm) 53 { 54 mm = seq[j]; 55 pos = j; 56 } 57 } 58 } 59 scanf("%d",&q); 60 while (q--) 61 { 62 int p; 63 scanf("%d",&p); 64 printf("%d\n",ans[p-1]); 65 } 66 } 67 return 0; 68 } 69 70 /************************************************************** 71 Problem: 1306 72 User: OUC_OptKernel 73 Language: C++ 74 Result: Accepted 75 Time:640 ms 76 Memory:1356 kb 77 Author:wangsouc 78 ****************************************************************/
C:凹凸曼和小怪兽的故事
【乱搞】枚举一个集合中的位置,再另一个集合中求最短距离。分别对x,y排序,乱搞。目测都是随机数据?如果有手动数据,应该可以卡掉这种贪心的。
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #define LL long long 6 #define max(a,b)a>b?a:b 7 #define min(a,b)a<b?a:b 8 #define maxn 100005 9 #define maxm 100000 10 #define inf 99999999999.0 11 using namespace std; 12 13 int n,a,b; 14 15 struct da{ 16 int x,y; 17 }A[maxn],B[maxn]; 18 19 bool cmp(da a,da b) 20 { 21 if(a.x == b.x) return a.y<b.y; 22 return a.x<b.x; 23 } 24 25 bool cmp1(da a,da b) 26 { 27 if(a.y == b.y) return a.x<b.x; 28 return a.y<b.y; 29 } 30 31 32 33 double get(int i,int j) 34 { 35 double x1 = (double)A[i].x; 36 double x2 = (double)B[j].x; 37 double y1 = (double)A[i].y; 38 double y2 = (double)B[j].y; 39 40 return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); 41 } 42 43 int find(int x) 44 { 45 if(x>B[n-1].x){ 46 return n-1; 47 }else if(x<=B[0].x){ 48 return 0; 49 } 50 51 int l,r,mid; 52 53 l = 0;r = n-1; 54 while(r>l) 55 { 56 mid = (r+l)/2; 57 58 if(B[mid].x == x){ 59 return mid; 60 }else if(B[mid].x > x){ 61 r = mid; 62 }else{ 63 l = mid+1; 64 } 65 } 66 67 return r; 68 } 69 70 int find1(int y) 71 { 72 if(y>B[n-1].y){ 73 return n-1; 74 }else if(y<=B[0].y){ 75 return 0; 76 } 77 78 int l,r,mid; 79 80 l = 0;r = n-1; 81 while(r>l) 82 { 83 mid = (r+l)/2; 84 85 if(B[mid].y == y){ 86 return mid; 87 }else if(B[mid].y > y){ 88 r = mid; 89 }else{ 90 l = mid+1; 91 } 92 } 93 94 return r; 95 } 96 97 int main() 98 { 99 while(scanf("%d%d%d",&n,&a,&b)!=-1) 100 { 101 for(int i=0;i<n;i++) 102 scanf("%d %d",&A[i].x,&A[i].y); 103 for(int i=0;i<n;i++) 104 scanf("%d %d",&B[i].x,&B[i].y); 105 106 sort(B,B+n,cmp); 107 108 double mi = inf; 109 110 for(int i=0;i<n;i++) 111 { 112 int x = find(A[i].x); 113 for(int j=-5;j<5;j++) 114 { 115 int s = x+j; 116 if(s>=n || s<0) continue; 117 118 mi = min(get(i,s),mi); 119 120 } 121 122 } 123 /* 124 sort(B,B+n,cmp1); 125 126 for(int i=0;i<n;i++) 127 { 128 int y = find1(A[i].y); 129 for(int j=-5;j<5;j++) 130 { 131 int s = y + j; 132 if(s>=n || s<0) continue; 133 134 mi = min(get(i,s),mi); 135 136 } 137 } 138 */ 139 printf("%.3lf\n",mi/(a+b)); 140 141 } 142 return 0; 143 } 144 145 /************************************************************** 146 Problem: 1309 147 User: OUC_OptKernel 148 Language: C++ 149 Result: Accepted 150 Time:32 ms 151 Memory:2540 kb 152 Author:S3_N 153 ****************************************************************/
D:算是模拟题,比较复杂,因为数据范围不大,为了节省代码量,可以写的复杂一些。
需要注意的,以前出现的包括所有周的,
struct node { string x; int y; int flag; int pre; }; node a[20][205]; int num[20]; int n1; int n ; int found; bool cmp(node a , node b) { return a.y > b.y; } void print() { for(int i = 1; i <= 16; i ++ ) printf("-"); } int main() { string s; n1 = 0 ; memset(num,0,sizeof(num)); while(scanf("%d",&n) != EOF && n != 0 ) { n1 ++ ; if(n1 != 1 ) { num[n1] = num[n1-1]; for(int i = 1 ; i <= num[n1] ; i ++ ) a[n1][i] = a[n1 - 1][i]; } for(int i = 1; i <= num[n1] ; i++ ) { a[n1][i].y = 0 ; a[n1][i].flag = 0; } int y; for(int i = 1; i <= n ; i ++ ) { cin >> s >> y ; // cout << y << endl; found = -1; for(int j = 1 ; j <= num[n1] ; j ++ ) { if(a[n1][j].x == s) { found = j; break; } } if(found == - 1 ) { num[n1] ++ ; a[n1][num[n1]].x = s ; a[n1][num[n1]].y = y; a[n1][num[n1]].flag = 3; a[n1][num[n1]].pre = 0; } else { a[n1][found].y = y; a[n1][found].pre = found; } } sort(a[n1] + 1 , a[n1] + num[n1] + 1 , cmp); int res; print();printf("WEEK %d",n1);print();printf("\n"); for(int i = 1 ;i <= 5; i ++ ) { printf("%d.",i); if(a[n1][i].flag == 3 ) printf("*NEW* "); else if(a[n1][i].flag == 0) { if(a[n1][i].pre > i ) printf("*UP* "); else if(a[n1][i].pre ==i) printf("*STAY* "); else printf("*DOWN* "); } cout << a[n1][i].x << endl; } } return 0; }
E:ZZY的宠物
【递推+矩阵乘法】记Fi,0<=i<=5是当前年龄为i的对数。Gi为下一个时刻对应年龄为i的对数。可写出递推公式:
G0 = 3*F1 + 2*F2 + 1*F3;Gi = Fi-1,i>=1.
然后矩阵乘法即可。
1 #include<stdio.h> 2 #include<math.h> 3 #include<string.h> 4 #define LL long long 5 #define MOD 10000 6 7 struct matrix{ 8 LL mat[6][6]; 9 void init(){ 10 memset(mat,0,sizeof(mat)); 11 } 12 void mod() 13 { 14 for (int i=0;i<6;i++) 15 for (int j=0;j<6;j++) 16 { 17 mat[i][j] = (mat[i][j] % MOD + MOD) % MOD; 18 } 19 return ; 20 } 21 void EE() 22 { 23 init(); 24 for (int i=0;i<6;i++) 25 mat[i][i] = 1; 26 return ; 27 } 28 29 }M,E; 30 31 32 void init() 33 { 34 M.init(); 35 M.mat[0][1] = 3; 36 M.mat[0][2] = 2; 37 M.mat[0][3] = 1; 38 for (int i=1;i<6;i++) 39 M.mat[i][i-1] = 1; 40 return ; 41 } 42 matrix mul(matrix a,matrix b) 43 { 44 matrix c; 45 c.init(); 46 47 for (int i=0;i<6;i++) 48 for (int j=0;j<6;j++) 49 { 50 c.mat[i][j] = 0; 51 for (int k=0;k<6;k++) 52 { 53 c.mat[i][j] = ((c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % MOD + MOD) % MOD; 54 } 55 } 56 c.mod(); 57 return c; 58 } 59 matrix power(matrix mm,LL n) 60 { 61 E.EE(); 62 while (n) 63 { 64 if (n %2 == 1) 65 { 66 E = mul(E,mm); 67 } 68 mm = mul(mm,mm); 69 n /= 2; 70 } 71 return E; 72 } 73 LL solve(LL n) 74 { 75 LL res = 0; 76 init(); 77 M = power(M,n); 78 for (int i=0;i<6;i++) 79 { 80 res = (res + M.mat[i][0]) % MOD; 81 } 82 return res; 83 } 84 85 int main() 86 { 87 LL n; 88 int cast = 0; 89 while (scanf("%lld",&n)==1){ 90 LL ans = solve(n); 91 ans = (ans*2) % MOD; 92 printf("Case %d: ",++cast); 93 printf("%lld\n",ans); 94 } 95 return 0; 96 } 97 98 /************************************************************** 99 Problem: 1313 100 User: OUC_OptKernel 101 Language: C++ 102 Result: Accepted 103 Time:124 ms 104 Memory:964 kb 105 Author:wangsouc 106 ****************************************************************/
F:ZZY的困惑
【枚举】数据较小直接枚举即可,时间O(2^m*m*n)。我写的dfs搜索。
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 int n; 5 int m; 6 int seq[22]; 7 int mat[22][22]; 8 int sum[22]; 9 int ans; 10 int p[22]; 11 int q[22]; 12 bool check(int tot) 13 { 14 memset(sum,0,sizeof(sum)); 15 for (int i=1;i<=tot;i++) 16 { 17 int u = p[i]; 18 for (int j=1;j<=n;j++) 19 sum[j] += mat[u][j]; 20 } 21 for (int i=1;i<=n;i++) 22 if (sum[i] < seq[i]) 23 return false; 24 return true; 25 } 26 void dfs(int deep,int tot) 27 { 28 if (deep > m) 29 { 30 if (!check(tot)) 31 return ; 32 33 if (tot == ans) 34 { 35 int flag = 0; 36 for (int i=1;i<=tot;i++){ 37 if (p[i] == q[i]){ 38 continue; 39 } 40 if (p[i] < q[i]){ 41 flag = 1; 42 }else{ 43 flag = 0; 44 } 45 break; 46 } 47 if (flag) 48 { 49 for (int i=1;i<=tot;i++) 50 { 51 q[i] = p[i]; 52 } 53 } 54 55 } 56 if (tot > ans) 57 { 58 ans = tot; 59 for (int i=1;i<=tot;i++) 60 q[i] = p[i]; 61 } 62 return ; 63 } 64 p[tot+1] = deep; 65 dfs(deep+1,tot+1); 66 dfs(deep+1,tot); 67 return ; 68 } 69 int main() 70 { 71 while (scanf("%d",&n)==1) 72 { 73 for (int i=1;i<=n;i++) 74 scanf("%d",&seq[i]); 75 scanf("%d",&m); 76 for (int i=1;i<=m;i++) 77 { 78 for (int j=1;j<=n;j++) 79 scanf("%d",&mat[i][j]); 80 } 81 ans = 0; 82 dfs(1,0); 83 84 printf("%d",ans); 85 for (int i=1;i<=ans;i++) 86 { 87 printf(" %d",q[i]); 88 } 89 printf("\n"); 90 } 91 return 0; 92 } 93 94 /************************************************************** 95 Problem: 1314 96 User: OUC_OptKernel 97 Language: C++ 98 Result: Accepted 99 Time:104 ms 100 Memory:964 kb 101 Author:wangsouc 102 ****************************************************************/
G:
【排序贪心】签到题,呵呵。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <ctime> 6 #include <cassert> 7 #include <iostream> 8 #include <sstream> 9 #include <fstream> 10 #include <map> 11 #include <set> 12 #include <vector> 13 #include <queue> 14 #include <algorithm> 15 #include <iomanip> 16 using namespace std; 17 18 #define abs(x) ((x)>=0?(x):-(x)) 19 #define i64 long long 20 #define u32 unsigned int 21 #define u64 unsigned long long 22 #define clr(x,y) memset(x,y,sizeof(x)) 23 #define PI acos(-1.0) 24 #define sqr(x) ((x)*(x)) 25 #define maxn 100 26 struct node 27 { 28 int t,id; 29 }; 30 node a[maxn]; 31 int n ; 32 bool cmp(node t1,node t2) 33 { 34 if(t1.t != t2.t) return t1.t < t2.t; 35 else return t1.id < t2.id; 36 } 37 int main() 38 { 39 while(scanf("%d",&n)!=EOF) 40 { 41 for(int i = 1 ; i <= n; i ++ ) 42 { 43 scanf("%d",&a[i].t); 44 a[i].id = i; 45 } 46 sort(a + 1 ,a + n + 1 ,cmp); 47 int sum1,sum2,base; 48 base = 0 ; 49 sum1 = 0 ; 50 sum2 = 0 ; 51 for(int i = 1; i <= n ; i ++ ) 52 { 53 base += a[i].t; 54 if(base > 300 ) break; 55 sum1 ++ ; 56 sum2 += base; 57 } 58 printf("%d %d\n",sum1,sum2); 59 for(int i = 1; i <= sum1 ; i++ ) 60 printf("%d\n",a[i].id); 61 } 62 return 0; 63 } 64 65 /************************************************************** 66 Problem: 1315 67 User: OUC_OptKernel 68 Language: C++ 69 Result: Accepted 70 Time:4 ms 71 Memory:1484 kb 72 Author:jh8180129 73 ****************************************************************/
H:协会的账目
题意:给一个序列,三种操作,在原序列的某个数后面插入一个数,如果之前有数了,那么插在这些数最后,两种查询,第一种查询,查询 最大的相邻的插值, 查询 最接近的两个数的差值。
只有插入没有删除,每次插入,会破坏一个关系,增加两个关系,并且破坏的关系只与原序列的每个数后面插入形成的小序列的头跟尾相关。第一种询问,维护一个最大堆即可,每次查询直接输出最大的即可,但为了方便删除,维护一个set也可以。第二个查询,直接维护这些数,每次添加一个新的数,查询这个集合中与该数最接近的两个数判断即可。
注意可能会有重复元素,维护multiset。
【multiset维护】:对于两种询问,维护两个multiset。求相邻差值最大,维护所有的相邻数的差值,对于插入一个数,破坏一组相邻关系,在集合中删除,会再增加两个关系,在集合中增加,直接查找集合最后元素即可。第二个操作,保留当前的最小值,即答案,每次增加数,在集合中查找与之最接近的数再判断更新答案即可,然后插入。每次插入,只需知道每个账目最后的收支金额和下一个账目的第一个收支金额,分别记录即可。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <ctime> 6 #include <cassert> 7 #include <iostream> 8 #include <sstream> 9 #include <fstream> 10 #include <map> 11 #include <set> 12 #include <vector> 13 #include <queue> 14 #include <algorithm> 15 #include <iomanip> 16 using namespace std; 17 18 #define abs(x) ((x)>=0?(x):-(x)) 19 #define i64 long long 20 #define u32 unsigned int 21 #define u64 unsigned long long 22 #define clr(x,y) memset(x,y,sizeof(x)) 23 #define PI acos(-1.0) 24 #define sqr(x) ((x)*(x)) 25 #define maxn 500100 26 #define pii pair<int,int> 27 #define inf 0x7ffffff 28 29 int head[maxn]; 30 int tail[maxn]; 31 int que[2*maxn]; 32 int n,m; 33 int _l1; 34 int cnt; 35 36 multiset<int> mp,mp1; 37 multiset<int>::iterator iter,it1; 38 39 int get(int x ) 40 { 41 int res ; 42 iter = mp.lower_bound(x); 43 it1 = iter; 44 if(iter == mp.end()) 45 { 46 --iter; 47 return abs(*iter - x); 48 } 49 iter = it1; 50 if(iter == mp.begin()) 51 { 52 res = abs(*iter - x); 53 iter ++ ; 54 if(iter != mp.end()) 55 res = min(res , abs( *iter - x ) ) ; 56 return res; 57 } 58 iter = it1; 59 res = abs(*iter - x ) ; 60 iter ++ ; 61 if(iter != mp.end()) 62 res = min(res , abs(*iter - x )); 63 iter -- ; 64 iter -- ; 65 res = min(res , abs(*iter - x )); 66 return res; 67 } 68 void update(int id,int x ) 69 { 70 int x1 ,x2 ,tmp; 71 x1 = que[tail[id]]; 72 if(id < n ) x2 = que[head[id+1]]; 73 if(id < n ) 74 { 75 tmp = abs(x1 - x2); 76 iter = mp1.find(tmp); 77 mp1.erase(iter); 78 } 79 mp1.insert(abs(x - x1)); 80 if(id < n ) mp1.insert(abs(x-x2)); 81 que[++cnt] = x; 82 tail[id] = cnt; 83 } 84 char str[105]; 85 int main() 86 { 87 while (scanf("%d%d",&n,&m) != EOF) 88 { 89 mp.clear(); 90 mp1.clear(); 91 _l1 = inf; 92 int tmp ; 93 for (int i=1; i<=n; i++) 94 { 95 head[i] = i; 96 tail[i] = i; 97 scanf("%d",&que[i]); 98 if(i > 1 ) 99 { 100 mp1.insert(abs(que[i]-que[i-1])); 101 } 102 if(mp.size() > 0 ) 103 { 104 tmp = get(que[i]); 105 if(tmp < _l1) 106 _l1 = tmp; 107 } 108 mp.insert(que[i]); 109 } 110 cnt = n ; 111 int id , x; 112 while (m--) 113 { 114 scanf("%s",str); 115 if (str[0] == 'I' && str[1]=='n') 116 { 117 scanf("%d%d",&id,&x); 118 update(id,x); 119 if(mp.size() > 0 ) 120 { 121 tmp = get(x); 122 if(tmp < _l1) 123 _l1 = tmp; 124 } 125 mp.insert(x); 126 } 127 else if (str[0] == 'M' && str[1] =='i') 128 { 129 printf("%d\n",_l1); 130 } 131 else if ( str[0] == 'M' && str[1]=='a') 132 { 133 // for(iter = mp1.begin() ; iter != mp1.end(); iter ++ ) 134 //{ 135 // printf("%d ",*iter); 136 // } 137 // printf("\n"); 138 iter = mp1.end(); 139 --iter; 140 printf("%d\n", *iter); 141 } 142 } 143 } 144 return 0; 145 } 146 147 /************************************************************** 148 Problem: 1316 149 User: OUC_OptKernel 150 Language: C++ 151 Result: Accepted 152 Time:400 ms 153 Memory:15636 kb 154 Author:jh8180129 155 ****************************************************************/
I:
题意:给定一个图,题目中的信息说明是一棵树,然后求最远的两个点之间的距离,注意有负权,如果全部为负权,那直接输出最大的值即可。
树形DP ,求直径,还可以两次dfs,比赛时候没想起是求直径,直接写dp了,还好代码不多。
直接遍历一边即可。假设以1为根。以u为根的子树,dfs后记录下子树中节点到u的最大值res1,和次大值res2(注意是不同分支中的),然后判断即可。答案在这些中
max(res1 , res2 ,res1 + res2 ),对每个遍历一遍,再判断一下全部是负权的情况。
#define maxn 50005 #define inf 0x3fffffffffffffff struct node { int v,next; long long w ; }; node e[maxn * 2 ]; int cnt ; int head[maxn]; long long dp[maxn][2]; void init() { cnt = 0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { e[cnt].v = v ; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt ++ ; e[cnt].v = u ; e[cnt].w = w ; e[cnt].next = head[v] ; head[v] = cnt ++ ; return ; } long long ans; long long dfs(int u ,int fa ) { int sons; long long res1 , res2 ; long long tmp ; res1 = res2 = -inf ; sons = 0 ; for(int i = head[u]; i != -1 ; i = e[i].next) if(e[i].v != fa ) { sons ++ ; tmp = e[i].w + dfs(e[i].v,u); if(tmp > res1) { res2 = res1; res1 = tmp; } else if(tmp > res2) { res2 = tmp; } } if(sons == 1 ) { ans = max(ans , res1); } else { ans = max(ans , res1 + res2); ans = max(ans , res1); } return max(0LL,res1); } int main() { long long _max; int n,m; while(scanf("%d%d",&n,&m)!=EOF) { init(); if(m != n - 1 ) { while(1 == 1 ) { int a ; a = 1 ; } } int u,v; long long w; _max = -inf ; for(int i = 1; i <= m ;i ++ ) { scanf("%d%d%lld",&u,&v,&w); add(u,v,w); _max = max(w,_max); } //printf("%lld\n",_max); long long tmp; ans = -inf ; tmp = dfs(1,0); // ans = max(ans , tmp ); ans = max(ans , _max); printf("%lld\n",ans); } return 0; }
【二分+最短路】题意求最大值最小,二分答案再求解即可。数据较大,使用spfa或者dij+堆。我写的spfa。
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<math.h> 5 #define maxn 2020 6 #define maxm 50500 7 8 struct edge{ 9 int u; 10 int v; 11 int val; 12 int next; 13 }e[2*maxm],seq[maxm]; 14 int last[maxn]; 15 int tot; 16 int n,m; 17 int A,B; 18 #define inf 100000000 19 20 void add(int u,int v,int val) 21 { 22 e[tot].v = v; 23 e[tot].val = val; 24 e[tot].next = last[u]; 25 last[u] = tot++; 26 return ; 27 } 28 void build(int val) 29 { 30 memset(last,-1,sizeof(last)); 31 tot = 0; 32 for (int i=1;i<=m;i++) 33 { 34 if (seq[i].val <= val) 35 { 36 add(seq[i].u,seq[i].v,seq[i].val); 37 add(seq[i].v,seq[i].u,seq[i].val); 38 } 39 } 40 return ; 41 } 42 int que[maxm]; 43 int dis[maxn]; 44 bool vis[maxn]; 45 46 int spfa() 47 { 48 memset(vis,0,sizeof(vis)); 49 for (int i=1;i<=n;i++) 50 { 51 dis[i] = inf; 52 } 53 int head = 0, tail = 0; 54 que[++tail] = A; 55 vis[A] = 1; 56 dis[A] = 0; 57 while (head < tail) 58 { 59 int u = que[++head]; 60 for (int j=last[u];j!=-1;j=e[j].next) 61 { 62 int v = e[j].v; 63 int val = e[j].val; 64 if (dis[u] + val < dis[v]) 65 { 66 dis[v] = dis[u] + val; 67 if (vis[v]==0) 68 { 69 vis[v] = 1; 70 que[++tail] = v; 71 } 72 } 73 } 74 vis[u] = 0; 75 } 76 if (dis[B] < inf) 77 return dis[B]; 78 return -1; 79 } 80 int solve() 81 { 82 int res = -1; 83 int l = 1, r = 10000; 84 while (l <= r) 85 { 86 int mid = (l + r)/2; 87 build(mid); 88 int tmp = spfa(); 89 if (tmp == -1) 90 { 91 l = mid + 1; 92 }else{ 93 res = tmp; 94 r = mid - 1; 95 } 96 } 97 return res; 98 } 99 int main() 100 { 101 while (scanf("%d%d%d%d",&n,&m,&A,&B)==4) 102 { 103 for (int i=1;i<=m;i++) 104 { 105 scanf("%d%d%d",&seq[i].u,&seq[i].v,&seq[i].val); 106 } 107 int ans = solve(); 108 printf("%d\n",ans); 109 } 110 return 0; 111 } 112 113 /************************************************************** 114 Problem: 1307 115 User: OUC_OptKernel 116 Language: C++ 117 Result: Accepted 118 Time:44 ms 119 Memory:3544 kb 120 ****************************************************************/
/******
OUC_OptKernel:首次AK,纪念。
******/