集训开始两个周了,一直没有做好总结,导致前两周时间没好好利用,接下来的日子里,要珍惜时间,勤于总结,多多反省,ice加油!!
-----2012年7月23日早
7.23 拓扑排序
定义:
拓扑排序,是指将一个有向无环图E(G)中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v>∈E(G),则u在线性序列中出现在v之前的排列方式.
本质:
对一个有向无环图G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前.
通常,满足这种线性次序的序列叫做拓扑序列.
特点(性质):
①若将图中顶点按拓扑次序排成一行,则图中所有的有向边均是从左指向右的.
②若图中存在有向环,则不可能使顶点满足拓扑次序.
③一个有向无环图的拓扑序列通常表示某种方案切实可行.
④一个有向无环图可能有多个拓扑序列.
拓扑排序,是指将一个有向无环图E(G)中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v>∈E(G),则u在线性序列中出现在v之前的排列方式.
本质:
对一个有向无环图G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前.
通常,满足这种线性次序的序列叫做拓扑序列.
特点(性质):
①若将图中顶点按拓扑次序排成一行,则图中所有的有向边均是从左指向右的.
②若图中存在有向环,则不可能使顶点满足拓扑次序.
③一个有向无环图的拓扑序列通常表示某种方案切实可行.
④一个有向无环图可能有多个拓扑序列.
//HDU3342 Legal or Not
#include<stdio.h>
#include<vector>
#include<string.h>
#include<iostream>
#define N 105
using namespace std;
int map[N][N], XX[N];
int main(){
int n , m , i , j , a , b ;
while( cin >> n >> m , n ){
memset( map, 0, sizeof(map) );
memset( XX , 0, sizeof(XX) );
for( i=1 ; i<=m ; i++){
cin >> a >> b ;
if(map[a][b])
continue ;
map[a][b] = 1 ;
XX[b]++ ;
}
int flag = 1 ;
for( int T=0 ; T<n ; T++){
for( i = 0 ;i < n ; i++ ) {
if( XX[i]==0 ) {
XX[i]--;
for(j = 0 ; j < n ; j++ )
if(map[i][j])
XX[j]-- ;
break ;
}
}
if(i>=n){
flag = 0 ;
break ;
}
}
if(!flag) puts("NO");
else puts("YES");
}
return 0;
}
//HDU1285 确定比赛名次
#include <string.h>
#include <iostream>
using namespace std;
int map[502][502], indegree[502], m, n, pur[502];
void topsort(){
int i , j , k=1;
for(i=1; i<=n; i++) {
for(j=1; j<=n; j++) {
if(indegree[j]==0) {
indegree[j]--;
pur[k++] = j;
for(int x=1; x<=n; x++)
if(map[j][x])
indegree[x]--;
break;
}
if(j>n) {
cout<<"存在环"<<endl;
return ;
}
}
}
}
int main(){
int i, j;
while(cin>>n>>m) {
memset(map,0,sizeof(map));
memset(indegree,0,sizeof(indegree));
int a, b;
for(i=1; i<=m; i++){
cin>>a>>b;
if(!map[a][b]){
map[a][b] = 1;
indegree[b]++;
}
}
topsort();
for(i=1; i<=n; i++)
if(i!=n)
cout<<pur[i]<<" ";
else
cout<<pur[i]<<endl;
}
return 0 ;
}
//HDU 2647 Reward
#include<stdio.h>
#include<vector>
#include<string.h>
#include<iostream>
#define N 10005
using namespace std;
vector<int>::iterator it;
int main(){
int n , m , i , a , b ;
while( cin >> n >> m){
int XX[N] = {0} ;
vector <int> map[N] ;
for( i=0 ; i<m ; i++){
cin >> a >> b;
map[b].push_back(a);
XX[a]++ ;
}
int T = n , flag = 1 , sum=0 , mon = 888 ;
while(T){
int Temp[N]={0} , k = 0 ;
for( i = 1 ;i <= n ; i++ ){
if( XX[i]==0 ){
T-- ;
XX[i]--;
Temp[k++] = i ;
sum += mon ;
if(T== 0) goto End;
}
}
for( i = 0 ;i < k ; i++ )
for( it = map[Temp[i]].begin() ; it < map[Temp[i]].end() ; it++ )
XX[*it]-- ;
if(!k){
flag = 0 ;
break ;
}
mon++ ;
}
End:;
if(!flag) puts("-1");
else printf("%d\n",sum);
}
return 0;
}
7.24上午 拓扑排序
艾玛,来就搞这个,搞了一上午,终于熟练了一点,还得多写代码,提高代码能力,加油// POJ1094 + NYOJ349 Sorting It All Out
//#define Judge_Online
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define N 27
using namespace std;
int ABC[N][N], Union[N] , Copy_Union[N] ,Ans[N];
bool flag1[N];
int n, m, flag ,Count , Count2;
void Set(char a, char b){
int x = a-'A', y = b-'A';
if(ABC[x][y]==0) {
ABC[x][y] = 1 ;
Union[y]++ ;
Count++;
if(!flag1[x]){
flag1[x] = 1 ;
Count2++;
}
if(!flag1[y]){
flag1[y] = 1 ;
Count2++;
}
}
memset(Ans,0,sizeof(Ans));
memcpy( Copy_Union, Union, sizeof(Union) );
int xx=Count2 ,temp = 0, aaa=0 ;
bool sss[N] = {0} ;
while(xx){
int Temp[N]={0}, k=0 ;
for(int i=0 ; i<n ; i++)
if(!Copy_Union[i] && flag1[i]){
Copy_Union[i]--;
xx--;
Ans[aaa++] = i ;
Temp[k++] = i ;
sss[i]=1;
if(xx==0)
break ;
}
if(!k){
flag = 1;
return ;
}
if(k!= 1 )
temp = 1 ;
// printf("%d %d %d\n",Count2 ,xx , k) ;
for(int i=0 ; i<k ; i++)
for(int j=0 ; j<n ; j++ )
if(ABC[Temp[i]][j] && !sss[j])
Copy_Union[j]--;
}
End:;
if(!temp){
for(int i=0 ; i<n ; i++)
if(!sss[i])
temp = 1 ;
if(!temp)
flag = 2;
}
}
int main(){
#ifdef Judge_Online
freopen( "Input.txt" ,"r", stdin );
#endif
char a, b, op;
while( cin >> n >> m ,m+n ){
memset(ABC,0,sizeof(ABC));
memset(Union,0,sizeof(Union));
memset(flag1,0,sizeof(flag1));
Count = 0;
Count2 = 0;
flag = 0;
for( int i=1 ; i<=m ; i++ ){
getchar();
cin >> a >> op >> b;
if(flag==0)
Set( a, b);
}
if(!flag)
puts("Sorted sequence cannot be determined.");
else if(flag==1)
printf("Inconsistency found after %d relations.\n",Count);
else{
printf("Sorted sequence determined after %d relations: ",Count);
for(int i=0 ; i<n ; i++)
printf("%c",Ans[i]+'A');
printf(".\n");
}
}
return 0;
}
7.24下午 最小生成树
进军
最小生成树,计划进行时间为
两天,加油!!
题目:布线问题
Prim版
#define Judge_Online
#include<stdio.h>
#include<string.h>
#include<iostream>
#define N 503
#define MAX 99999999
using namespace std;
int map[N][N], n , MinSum , LowCost[N];
void Prim(){
for(int i=1;i<=n;i++) //初始化
LowCost[i]=map[1][i];
LowCost[1]=0; //等于零表示在最小路径集合中
for(int i=2;i<=n;i++){
int k,minn=MAX;
for(int j=2;j<=n;j++) { //找最小边
if(LowCost[j]<minn&&LowCost[j]!=0){
minn=LowCost[j];
k=j;
}
}
MinSum += minn ;
LowCost[k]=0;
for(int j=2;j<=n;j++)
if(map[k][j]<LowCost[j])
LowCost[j]=map[k][j];
}
}
int main(){
#ifdef Judge_Online
freopen( "Input.txt", "r" , stdin );
#endif
int cases, m, j, x, y, Min;
scanf( "%d", &cases );
while( cases-- ){
memset( map , 0, sizeof(map));
Min = MAX ;
scanf( "%d%d" , &n, &m );
for( int i=0 ; i<m ; i++){
scanf( "%d%d%d" , &x, &y, &j);
map[x][y] = j;
map[y][x] = j;
}
for( int i=0 ; i<n ; i++ ){
scanf( "%d" , &j);
Min = min( Min , j );
}
MinSum = 0;
Prim();
printf( "%d\n" , MinSum+Min );
}
return 0;
}