青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆:78 文章:7 評論:38 引用:0
C++博客 首頁 發新隨筆
發新文章 聯系 聚合管理

題目大意:給定兩個區間,[a,b] [c,d] 設x屬于第一個區間,y屬于第二個區間,求gcd(x,y)=k的實數對有多少個。
方法:對兩個區間分別除以k,轉化為求新區間內,互質的實數對有多少個。
容斥原理:|t1Ut2U...Utn| = sum[ti] - sum[ti n tj] + sum[ti n tj n tk] - ... + (-1)^(m+1)|t1 n t2 n ... n tn|
把所有有是1的倍數的點對加起來  減去既有1也有(2,3,5。。。)的點對   加上既有1也有2也有3.。的點對


#include <stdio.h>
#include 
<algorithm>
using namespace std;

bool mark[100010];
int prim[10000], tot =0, sum = 0;
struct node{
     
int v; //v存的是數  就是乘積  k是記錄減還是加
     
int k;
}tb[
70000];

void di(long long p,int k,int odd) {//奇數個因數的就加 偶數個因數的就減
     
if (k == tot) return;
     
long long tmp = p*prim[k]; 
     
if (tmp > 100000return;
     di(p,k
+1,odd);
     tb[sum].v 
= tmp;
     tb[sum
++].k = -odd;
     di(tmp,k
+1,-odd);
}

void swap(int &a,int &b) {
     a 
+= b;
     b 
= a-b;
     a 
= a-b;
}

int cmp(node a,node b) {
    
return a.v < b.v;
}

int main () {
    
int i, j;
    
for (i = 2; i <= 100000; i++) {
        
if (!mark[i]) {
           prim[tot
++= i;
           
for (j = i+i; j <= 100000; j += i)
               mark[j] 
= 1;
        }
    }
    tb[
0].v = 1; tb[0].k = 1;
    sum 
= 1;
    di(
1,0,1);
    sort(tb,tb
+sum,cmp);
    
int kase, a, b, c, d, k, o = 1;
    scanf(
"%d"&kase);
    
while (kase--) {
          scanf(
"%d %d %d %d %d"&a, &b, &c, &d, &k);
          
if (k == 0) {
             printf(
"Case %d: 0\n", o++);
             
continue;
          }
          
int x = b/k;
          
int y = d/k;
          
if (x == 0 || y == 0) {
             printf(
"Case %d: 0\n", o++);
             
continue;
          }
          
if (x > y) swap(x,y);
          
long long ans = 0;
          
for (i = 0; i < sum; i++) {
              
if (x < tb[i].v) break;
              
long long tmpx = x/tb[i].v;
              
long long tmpy = y/tb[i].v;
              
long long c = tmpx*tmpy-(tmpx-1)*tmpx/2;
              ans 
+= c*tb[i].k;
          }
          printf(
"Case %d: %I64d\n",o++,ans);
    }
    
return 0;    
}





posted @ 2009-10-09 00:17 未央 閱讀(396) | 評論 (0)編輯 收藏
 
pku 2186
注意此題是單case,若想統計有幾個連通分量可以根據belong數組進行操作。
#include<iostream>
#incldue
<string.h>
#include
<stdlib.h>
#include
<stdio.h>
#define N1 50005
using namespace std;
struct Edge
{
    
int a, b;
}edges[N1];
bool visited[N1];//深搜時候,記錄節點是否被訪問過
int N,M;
int end_order[N1];//記錄深搜的時候,節點訪問結束順序
int index;
int first[N1]; //用于存儲圖,first[i]指向第一條起始節點為i的邊
int belong[N1];//belong[i]記錄節點i屬于哪個強連通分量
int cnt[N1]; //cnt[i]記錄節點i強連通分量中節點的數量
bool is_out[N1]; //is_out[i]記錄第i個強連通分量是否有出邊
int cmp1(const void *a, const void *b)
{
    
return ((Edge*)a)->a-((Edge*)b)->a;
}
int cmp2(const void *a, const void *b)
{
    
return ((Edge*)a)->b-((Edge*)b)->b;
}
void dfs1(int source)
{
    
if(visited[source]) return ;
    visited[source]
=true;
    
for(int i=first[source]; i<first[source+1]; i++)
        dfs1(edges[i].b);
    end_order[index
++]=source;//記錄節點訪問結束順序
}
void dfs2(int source ,int k)
{
    
if(visited[source]) return ;
    visited[source]
=true;
    
for(int i=first[source]; i<first[source+1]; i++)
        dfs2(edges[i].a, k);
    belong[source]
=k;//記錄節點所屬的強連通分量
    cnt[k]++;//強連通分量內節點計數
}
int main()
{
    
int ans;
    scanf(
"%d %d"&N, &M);
    
for(int i=0; i<M; i++){
        scanf(
"%d %d"&edges[i].a, &edges[i].b);
        edges[i].a
--; edges[i].b--;
    }
    edges[M].a
=edges[M].b=-1//簡化下面first數組的構建
    qsort(edges, M, sizeof(edges[0]), cmp1);
    
int last_source=0;
    first[last_source]
=0;
    
int k=0;
    
while(last_source<N){
        
if(edges[k].a==last_source) k++;
        
else first[++last_source]=k;
    }
    memset(visited, 
0sizeof(visited));
    index
=0;
    
for(int i=0; i<N; i++)
        dfs1(i);
    qsort(edges, M , 
sizeof(edges[0]), cmp2);
    last_source
=0;
    first[last_source]
=0;
    k
=0;
    
while(last_source<N){
        
if(edges[k].b==last_source) k++;
        
else first[++last_source]=k;
    }
    memset(visited, 
0sizeof(visited));
    memset(cnt, 
0sizeof(cnt));
    k
=0;
    
for(int i=index-1; i>=0; i--){
        
if(visited[end_order[i]]) continue;
        dfs2(end_order[i], k); 
//第二次搜索
        k++;
    }
    
for(int i=0; i<M; i++){//記錄哪些強連通分量有出邊
        if(belong[edges[i].a]!=belong[edges[i].b])
            is_out[belong[edges[i].a]]
=true;
    }
    
int no_out=0;
    
for(int i=0; i<k; i++){//統計無出邊的強連通分量的個數
        if(!is_out[i]){
            no_out
++;
            ans
=cnt[i];
        }
    }
    
if(no_out==1)//輸出
        printf("%d\n", ans);
    
else
        printf(
"0\n");

    
return 0;
}
posted @ 2009-09-16 11:44 未央 閱讀(350) | 評論 (0)編輯 收藏
 
pku1639
這題郁悶啊,手抄prayer的模板都抄不對~~~
#include<iostream>
#include
<algorithm>
#include
<cstring>
#include
<map>
#include
<stdio.h>
#include
<string>
#define N1 110
using namespace std;
int const INF=100000000;
int cost[N1][N1];//花費 = 邊
int used[N1][N1];//表示這條邊是否在生成樹中
int father[N1];//生成樹中點的父節點
int maxlen[N1];//表示i點到根路徑上除了與根直接相連的邊外,邊權最大的邊權
int vis[N1];//標記
int d[N1]; //求最小生成樹時的最小生成樹代價
int AnsMst;//當前m度生成樹的代價
int N, degree, lim;//degree表示最小限度,lim表示限度值
int g[N1][N1];//生成樹中的兒子關系,正向表
map<stringint> mat;
void MST(int S) //求從S點開始的最小生成樹
{
    
while(1){
        
int K=-1;
        
for(int i=1; i<=N; i++){
            
if(!vis[i] && d[i]!=INF && (K==-1||d[K]>d[i]))
                K
=i;
        }
        
if(K==-1break;
        vis[K]
=1;
        AnsMst
+=d[K];
        g[father[K]][
++g[father[K]][0]]=K;//記錄兒子
        if(d[K]!=0) maxlen[K] = max(maxlen[father[K]], d[K]);//算邊權最大的邊
        used[K][father[K]] = used[father[K]][K] = 1;//標記邊在生成樹中
        for(int i=1; i<=N; i++){
            
if(!vis[i] && cost[K][i]<d[i]){
                father[i]
=K;
                d[i]
=cost[K][i];
            }
        }
    }
}
void Build()
{
    
for(int i=1; i<=N; i++)
        father[i]
=i;
    
for(int i=1; i<=N; i++)
        d[i]
=INF;
    
for (int i = 1; i <= N; i++)
        
for (int j = 1; j <= N; j++)
        used[i][j] 
= 0;//所有的邊都在生成樹外
    for(int i=1; i<=N; i++)
        g[i][
0]=0//兒子數全為0
    for (int i = 1; i <= N; i++) vis[i] = 0// 標記清空
    vis[1]=1;
    degree
=0;
    maxlen[
1]=-INF; //根的maxlen為-INF;
    AnsMst=0//開始時生成樹的代價為0
    while(1){
        
int K=-1;
        
for(int i=1; i<=N; i++){
            
if(!vis[i] && (K==-1 ||cost[1][i]<cost[1][K]))
                K
=i; //找個距根邊權最小的點開始做最小生成樹
        }
        
if(K==-1break;
        father[K]
=1//father 為 1
        maxlen[K]=-INF; //maxlen[k]=--INF;
        d[K]=0;
        degree
++;//連通分支個數加1
        AnsMst+=cost[1][K]; //生成樹代價增加

        MST(K);
    }
}
void Init()//開始的輸入處理
{
    mat.clear();
    mat[
"Park"]=1;
    N
=1;
    
int M;
    scanf(
"%d"&M);
    
for(int i=1; i<=30; i++)
        
for(int j=1; j<=30; j++)
            cost[i][j]
=INF;
    
while(M--){
        
string a, b;
        
int c;
        cin
>>a>>b>>c;
        
int ida, idb;
        
if(mat.find(a)==mat.end()) mat[a]=++N, ida=N;
        
else ida=mat[a];
        
if(mat.find(b)==mat.end()) mat[b]=++N, idb=N;
        
else idb=mat[b];
        cost[ida][idb]
=cost[idb][ida]=c;
    }

    scanf(
"%d"&lim);
}
void Dfs(int nod, int fa) //更新維護maxlen和生成樹中的父子關系
{
    father[nod]
=fa;
    vis[nod]
=1;
    
if(fa==1) maxlen[nod]=-INF;
    
else
        maxlen[nod]
=max(maxlen[fa], cost[nod][fa]);
    
for(int i=1; i<=g[nod][0]; i++)
        
if(used[nod][g[nod][i]]&&!vis[g[nod][i]])
            Dfs(g[nod][i], nod);
}
void Solve(){
    
if(degree>lim)
        printf(
"Error\n");
    
int ans=AnsMst;
    
while(degree<lim){
        degree
++;
        
int id=-1;
        
int delta=INF;
        
for(int i=1; i<=N; i++){//找代價最小的進行擴張
            if(cost[1][i]!=INF && !used[1][i]){
                
if(id==-1){
                    id
=i;
                    delta
=cost[1][i]-maxlen[i];
                    
continue;
                }
                
if(cost[1][i]-maxlen[i]<delta){
                    id
=i;
                    delta
=cost[1][i]-maxlen[i];
                }
            }
        }
        
if(id==-1){ break;}
        AnsMst
+=delta;//加上delta值
        ans=min(ans, AnsMst);
        
int Len=maxlen[id];
        used[
1][id]=used[id][1]=1;//表示邊被加入到當前的生成樹中
        g[1][++g[1][0]]=id; //表示根多加了一個兒子
        while(cost[id][father[id]]!=Len){//找最大的邊,并順路維護兒子關系
            int fa=father[id];
            g[id][
++g[id][0]]=fa;
            id
=fa;
        }
        used[id][father[id]]
=used[father[id]][id]=0;//標記邊被刪去
        for(int i=1; i<=N; i++)
            vis[i]
=0;
        Dfs(
11);//維護
    }
    printf(
"Total miles driven: %d\n", ans);
}
int main()
{
    Init();
    Build();
    Solve();

    
return 0;
}
posted @ 2009-09-16 08:39 未央 閱讀(453) | 評論 (0)編輯 收藏
 

先討論有根樹同構

試圖確定兩顆樹的最小表示,如果最小表示相同則同構

明確一下樹的大小判斷標準:

①     根節點度數大的樹大

②     根節點度數一樣時,將子樹排序,然后依次判斷每個子樹,第一個子樹大的樹大

復雜度分析:

時間:排序均用快排,compare的復雜度是O(n),快速排序進行nlogn次compare,排序的復雜度是O(n2logn)更新link的復雜度為O(n2logn),計算rank的復雜度為O(n2),總的時間復雜度是O(n2logn)(上述考慮的是最壞情況,實際情況原小于理論值)


有根樹的同構pku1635
#include<stdio.h>
#include
<string.h>
#include
<algorithm>
#include
<stdlib.h>
#include
<vector>
using namespace std;
const int Mod = 9901;
const int Max = 3010;
const int Mul = 9110;
vector
<int> adj[Max];
int father[Max], hash[Max];
bool cmp(int a, int b)
{
    
return hash[a]<hash[b];
}
int rebuild(char *str)
{
    
for(int i=0; i<Max; i++)
        adj[i].clear();
    
for(int i=0, j=1, k=0; str[i]; i++){
        
if(str[i]=='0'){
            adj[k].push_back(j);
            father[j]
=k;
            k
=j;
            j
++;
        }
        
else
            k
=father[k];
    }
    
return 0;
}
int dfs(int k)
{
    
int val = 0;
    
if(adj[k].size()==0)
        val
=1;
    
else{
        
for(int i=0; i<adj[k].size(); i++){
            
int j=adj[k][i];
            hash[j]
=dfs(j);
        }
        sort(adj[k].begin(), adj[k].end(), cmp);
        val
=1908;
        
for(int i=0; i<adj[k].size(); i++){
            
int j=adj[k][i];
            val
=((val*Mul)^hash[j])%Mod;
        }
    }
    
return val;
}
int main()
{
    
int i,j,n;
    
char s[Max];
    scanf(
"%d",&n);
    
while(n--){
        
int hash1, hash2;
        scanf(
"%s", s); //讀入一個01字符串,0代表遠離根節點,1代表靠近根節點
        rebuild(s);
        hash1
=dfs(0);
        scanf(
"%s",s);
        rebuild(s);
        hash2
=dfs(0);
        printf(
"%s\n", hash1==hash2?"same":"different");
    }
    
return 0;
}

對于無根樹,只要確定一個根,就轉換成有根樹同構的判斷了

將樹看成無向圖,進行拓撲排序(每次刪除度為1的點),最后剩余1或2個點。

如果是1個點,以該點為根建立有根樹

如果是2個點,一棵樹以任一點為根建樹,另一棵樹分別以2個點建立樹,判斷兩次。

2009合肥賽區網絡預賽 ustc 1117 Bean Language

#include<stdio.h>
#include
<string.h>
#include
<algorithm>
#include
<stdlib.h>
#include
<vector>
using namespace std;
const int Mod = 9901;
const int Max = 1010//節點數
const int Mul = 9110;
vector
<int> adj[Max];
int g[Max][Max], q[Max], level[Max], visit[Max];
int father[Max], hash[Max], one[2], two[2];
bool cmp(int a, int b)
{
    
return hash[a]<hash[b];
}
void Top(int n, int x) //拓撲排序找根
{
    memset(visit, 
0sizeof(visit));
    
int head=0, tail=0;
    
for(int i=0; i<n; i++){
        
if(g[i][n]==1){
            visit[i]
=1;
            level[tail]
=0;
            q[tail
++]=i;
        }
    }
    
while(head<tail){
        
int now=q[head], l=level[head++];
        
for(int i=0; i<n; i++)
            
if(!visit[i] && g[now][i]){
                g[i][n]
--;
                
if(g[i][n]<=1){
                    level[tail]
=l+1;
                    q[tail
++]=i;
                    visit[i]
=1;
                }
            }
    }
    
int l=level[tail-1], k=0;
    
for(int i=tail-1; level[i]==l; i--){
        
if(k==0){
            one[x]
=q[i]; k++;
        }
        
else
            two[x]
=q[i];
    }
}
void build(int root, int n) 
{
    visit[root]
=1;
    
for(int i=0; i<n; i++){
        
if(!visit[i] && g[root][i]){
            adj[root].push_back(i);
            build(i, n);
        }
    }
}
int dfs(int k)
{
    
int val = 0;
    
if(adj[k].size()==0)
        val
=1;
    
else{
        
for(int i=0; i<adj[k].size(); i++){
            
int j=adj[k][i];
            hash[j]
=dfs(j);
        }
        sort(adj[k].begin(), adj[k].end(), cmp);
        val
=1908;
        
for(int i=0; i<adj[k].size(); i++){
            
int j=adj[k][i];
            val
=((val*Mul)^hash[j])%Mod;
        }
    }
    
return val;
}
int main()
{
    
int i,j,n,cas,a,b;
    
char s[Max];
    scanf(
"%d",&cas);
    
while(cas--){
        
int hash1, hash2;
        scanf(
"%d",&n);  //讀入n個節點
        memset(g, 0sizeof(g));
        one[
0]=-1; one[1]=-1; two[0]=-1; two[1]=-1;
        
for(i=0; i<n-1; i++){ //n-1條邊,無重邊
            scanf("%d %d"&a, &b);
            a
--; b--;
            g[a][b]
++; g[b][a]++;
            g[a][n]
++; g[b][n]++;
        }
        Top(n,
0);
        memset(visit, 
0sizeof(visit));
        
for(int i=0; i<n; i++)
            adj[i].clear();
        build(one[
0],n);
        hash1
=dfs(one[0]);
        memset(g, 
0sizeof(g));
        
for(i=0; i<n-1; i++){
            scanf(
"%d %d"&a, &b);
            a
--; b--;
            g[a][b]
++; g[b][a]++;
            g[a][n]
++; g[b][n]++;
        }
        Top(n,
1);
        memset(visit, 
0sizeof(visit));
        
for(int i=0; i<n; i++)
            adj[i].clear();
        build(one[
1],n);
        hash2
=dfs(one[1]);
        
if(hash1!=hash2 && two[1]!=-1){
            memset(visit, 
0sizeof(visit));
            
for(int i=0; i<n; i++)
                adj[i].clear();
            build(two[
1],n);
            hash2
=dfs(two[1]);
        }
    
//    printf("%d %d %d %d\n", one[0], two[0], one[1], two[1]);
        printf("%s\n", hash1==hash2?"same":"different");
    }
    
return 0;
}
posted @ 2009-09-06 22:30 未央 閱讀(5318) | 評論 (8)編輯 收藏
 
樸素的prim,還是自己寫的用著習慣
pku 1251
#include<stdio.h>
#include
<string.h>
#define N 30
#define M 1<<27
int g[N][N],n; //g[][]的初值為M, 下標從0開始
int prim()
{
    
int i,j,k,ans=0;
    
int dis[N], visit[N], pre[N];
    
for(i=0; i<n; i++){
        dis[i]
=g[0][i];
        visit[i]
=0;
        pre[i]
=0;
    }
    visit[
0]=1;
    
for(i=1; i<n; i++){
        
int mn=M, v=0;
        
for(j=0; j<n; j++)
            
if(!visit[j] && dis[j]<mn){
                mn
=dis[j];
                v
=j;
            }
        
if(v==0break;
        visit[v]
=1;
        ans
+=mn;
        
for(j=0; j<n; j++)
            
if(!visit[j] && dis[j]>g[v][j]){
                dis[j]
=g[v][j];
                pre[j]
=v;
            }
    }
    
return ans;
}
int main()
{
    
int i,j,k,p,q,z;
    
char s[5];
    
while(scanf("%d"&n) && n){
        
for(i=0; i<n; i++)
            
for(j=0; j<n; j++)
                g[i][j]
=M;
        
for(i=0; i<n-1; i++){
            scanf(
"%s %d", s, &k);
            p
=s[0]-'A';
            
for(j=0; j<k; j++){
                scanf(
"%s %d", s, &z);
                q
=s[0]-'A';
                g[p][q]
=g[q][p]=z;
            }
        }
        printf(
"%d\n", prim());

    }
    
return 0;
}
posted @ 2009-09-04 21:14 未央 閱讀(250) | 評論 (0)編輯 收藏
 
先做一遍prim,求出最小生成樹的value,和路徑。每次去掉一條路徑上的邊,再做最小生成樹,若出現新的value和第一次的value相等,則次小生成樹不唯一。否則,取枚舉過程中最小的一個value即可。
#include<stdio.h>
#include
<string.h>
#define N 110
#define M 1<<27
int g[N][N], pre[N],low[N];
bool visit[N];
struct Now
{
    
int x, y, z;
}now[N], cur;
int prim(int n){
    
int i,j,k, ans=0;

    
for(i=1; i<=n; i++){
        low[i]
=g[1][i];
        pre[i]
=1;
        visit[i]
=false;
    }
    visit[
1]=true;
    k
=1;
    
for(i=2; i<=n; i++){
        
int mn=-1, p;
        
for(j=1; j<=n; j++)
            
if(!visit[j] && (mn==-1 || low[j]<mn)){
                mn
=low[j];
                p
=j;
            }
            
if(mn==-1break;
            ans
+=mn;
            k
=p;
            visit[k]
=true;
            
for(j=1; j<=n; j++){
                
if(!visit[j] && low[j]>g[k][j]){
                    low[j]
=g[k][j];
                    pre[j]
=k;
                }
            }

        }
    
return ans;
}
int main()
{
    
int i,j,n,m,ca,x,y,z;
    scanf(
"%d"&ca);
    
while(ca--){
        scanf(
"%d %d"&n, &m);
        
for(i=0 ; i<=n ; i++)
            
for(j=0; j<=n; j++)
                g[i][j]
=M;
        
for(i=0; i<m; i++){
            scanf(
"%d %d %d"&x, &y, &z);
            g[x][y]
=g[y][x]=z;
        }
        
int value=prim(n);
        j
=0;
        
for(i=2; i<=n; i++){
            now[j].x
=i;
            now[j
++].y=pre[i];
        }
        
int t=0;
        
for(i=0; i<n-1; i++){
            
int a, b, aa, bb;
            a
=now[i].x;
            b
=now[i].y;
            now[i].z
=g[a][b];
            g[a][b]
=g[b][a]=M;
            
if(i>0){
                aa
=now[i-1].x;
                bb
=now[i-1].y;
                g[aa][bb]
=g[bb][aa]=now[i-1].z;
            }
            
int tmp=prim(n);
            
if(tmp==value){
                t
=1;
                
break;
            }
        }
        
if(t)
            printf(
"Not Unique!\n");
        
else
            printf(
"%d\n", value);
    }
    
return 0;
}
posted @ 2009-09-03 22:10 未央 閱讀(228) | 評論 (0)編輯 收藏
 
首先為除根之外的每個點選定一條入邊,這條入邊一定要是所有入邊中最小的
除第一個點外,在另外點上找是否有向環的起點
如果有,先把環上邊權加到res中,標記環上的點,再調整有向環的起點上的入邊
調整有向環上其它點的入邊和出邊(取環上點到非環上點的最小值為環到k的值)(把環上點縮到i上)
如果找全就跳出返回最小樹形圖的值
調整的時候入邊要減掉in[u];

//pku 3164
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 110
#define M 1<<27
struct P
{
 double x, y;
}p[N];
double g[N][N],ans;
int visit[N],n,m,pre[N],circle[N],del[N];
double minn(double a, double b)
{
 return a<b?a:b;
}
double dis(P a, P b)
{
 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void dfs(int x)
{
 for(int i=1; i<=n; i++)
  if(!visit[i] && g[x][i]!=M){
   visit[i]=1;
   dfs(i);
  }
}
int exist(){//判連通
 int i,root=1;
 memset(visit, 0, sizeof(visit));
 visit[root]=true;
 dfs(root);
 for(i=1; i<=n; i++)
  if(!visit[i])
   return 0;
 return 1;
}
void S_Tree()
{
 int i,j,k,in,mark;
 memset(del, 0, sizeof(del));
 while(1){
 for(i=2; i<=n; i++)
  if(!del[i]){//找每個點的最小入度
   pre[i]=i;
   g[i][i]=M;
   for(j=1; j<=n; j++)
    if(!del[j] && g[j][i]<g[pre[i]][i]){
     pre[i]=j;
    }
  }
 for(i=2; i<=n; i++)
  if(!del[i]){
   memset(visit, 0, sizeof(visit));
   mark=i;
   while(!visit[mark] && mark!=1){//找環
    visit[mark]=1;
    mark=pre[mark];
   }
   if(mark==1) //若無環,則必會找到根節點,continue;
    continue;
   i=mark;    //否則就有環
   ans+=g[pre[i]][i];      
   for(j=pre[i]; j!=i; j=pre[j]){
    ans+=g[pre[j]][j];        //加環上的權值
    del[j]=1;
   }
   for(j=1; j<=n; j++)  //處理外界點與環上點的權值
    if(!del[j]){
     if(g[j][i]!=M)
      g[j][i]-=g[pre[i]][i];
    }
   for(j=pre[i]; j!=i; j=pre[j]){  //處理環上點與外界點的權值
    for(k=1; k<=n; k++)
     if(!del[k]){
      g[i][k]=minn(g[i][k], g[j][k]);
      if(g[k][j]!=M){
       g[k][i]=minn(g[k][i], g[k][j]-g[pre[j]][j]);
      }
     }
   }
   break;//做完一次縮點工作就跳出,繼續生成新的圖
  }
  if(i>n){
   for(j=2; j<=n; j++)
    if(!del[j]){
     ans+=g[pre[j]][j];
    }
   break;
  }
 }
}
int main()
{
 int i,j,k;
 while(scanf("%d %d",&n, &m)!=EOF){
  ans=0;
  for(i=1; i<=n; i++)
   for(j=1; j<=n; j++)
    g[i][j]=M;
  for(i=1; i<=n; i++)
   scanf("%lf %lf", &p[i].x, &p[i].y);
  for(i=0; i<m; i++){
   scanf("%d %d", &j, &k);
   g[j][k]=dis(p[j], p[k]);
  }
  i=exist();
  if(!exist())
   printf("poor snoopy\n");
  else{
   S_Tree();
   printf("%.2lf\n", ans);
  }
 }

 return 0;
}



posted @ 2009-08-31 11:04 未央 閱讀(511) | 評論 (0)編輯 收藏
 
這是個很完善的模板O(∩_∩)O~
#include <stdio.h>
#include 
<math.h>
const int N = 100010;
int mark[N];
struct Point
{
    
double x,y;
};
struct stline
{
    Point a,b;
} line1,line2, p[N];

int dblcmp(double a,double b)
{
    
if (fabs(a-b)<=1E-6return 0;
    
if (a>b) return 1;
    
else return -1;
}
//***************點積判點是否在線段上***************
double dot(double x1,double y1,double x2,double y2) //點積
{
    
return x1*x2+y1*y2;
}

int point_on_line(Point a,Point b,Point c) //求a點是不是在線段bc上,>0不在,=0與端點重合,<0在。
{
    
return dblcmp(dot(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y),0);
}
//**************************************************
double cross(double x1,double y1,double x2,double y2)
{
    
return x1*y2-x2*y1;
}
double ab_cross_ac(Point a,Point b,Point c) //ab與ac的叉積
{
    
return cross(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
int ab_cross_cd (Point a,Point b,Point c,Point d) //求ab是否與cd相交,交點為p。1規范相交,0交點是一線段的端點,-1不相交。
{
    
double s1,s2,s3,s4;
    
int d1,d2,d3,d4;
    Point p;
    d1
=dblcmp(s1=ab_cross_ac(a,b,c),0);
    d2
=dblcmp(s2=ab_cross_ac(a,b,d),0);
    d3
=dblcmp(s3=ab_cross_ac(c,d,a),0);
    d4
=dblcmp(s4=ab_cross_ac(c,d,b),0);

//如果規范相交則求交點
    if ((d1^d2)==-2 && (d3^d4)==-2)
    {
        p.x
=(c.x*s2-d.x*s1)/(s2-s1);
        p.y
=(c.y*s2-d.y*s1)/(s2-s1);
        
return 1;
    }

//如果不規范相交
    if (d1==0 && point_on_line(c,a,b)<=0)
    {
        p
=c;
        
return 0;
    }
    
if (d2==0 && point_on_line(d,a,b)<=0)
    {
        p
=d;
        
return 0;
    }
    
if (d3==0 && point_on_line(a,c,d)<=0)
    {
        p
=a;
        
return 0;
    }
    
if (d4==0 && point_on_line(b,c,d)<=0)
    {
        p
=b;
        
return 0;
    }
//如果不相交
    return -1;
}
posted @ 2009-08-24 10:36 未央 閱讀(3852) | 評論 (0)編輯 收藏
 
經歷了各種TLE,各種WA,還有一次RE,終于在網上找到兩句至理名言,靠這兩個剪枝,在北大上AC了這道錯了25次的1011.
但不行的是在Hdu,依然WA中,預知后事如何,請聽下回分解。
強大的剪枝!
1.搜索每根大木棍的時候,如果因為安放了第一段木棍就無法提供合理解的時,就不用去試探其他小木棍在第一段位置的情況了。所以回溯到上一個大木棍的搜索,是第一個大木棍的第一段出現問題,那么該長度肯定不符合要求。

2.每個大木棍的最后一段,如果不合要求,那么也不用去試圖去安放其他的小木棍了,直接回溯到上段木棍即可。因為,換成更小的木棍,即便也可使木棍填滿,小木棍也有可能在將來的時候無法安放。簡單的說,如果它不行,采用別的更小的木棍也不行;如果它可以,采用別的更小的木棍也一定可以。

#include<stdio.h>
#include
<algorithm>
#include
<string.h>
using namespace std;
int a[100],n,sum, get, mark[100];
int cmp(int c, int b)
{
    
return c>b;
}
int dfs(int nowlen, int nowget, int nowi)
{
    
for(int i=nowi; i<n; i++)
        
if(mark[i]==0 && nowlen>=a[i]){
            mark[i]
=1;
            
if(nowlen>a[i]){
                
if(dfs(nowlen-a[i], nowget, i+1)==1)
                    
return 1;
                
else if(nowlen==sum/get//剪枝1
                { mark[i]=0;    return 0; }
            }
            
else if(nowlen==a[i]){
                
if(nowget+1==getreturn 1;
                
if(dfs(sum/get, nowget+10)==1)
                    
return 1;
                
else{
                    mark[i]
=0;//剪枝2
                    return 0;
                }
            }
        mark[i]
=0;
        }


    
return 0;
}
int main()
{
    
int i,j,k;
    
while(scanf("%d",&n) && n){
        sum
=0;
        memset(a, 
0sizeof(a));
        
for(i=0; i<n; i++){
            scanf(
"%d",&a[i]);
            sum
+=a[i];
        }
        sort(a, a
+n, cmp);
        
get=sum/a[0];
        
while(sum%get!=0){
            
get--;
        }
        
while(1){
            memset(mark, 
0sizeof(mark));
            
if(dfs(sum/get00)==1)
                
break;
            
else{
                
get--;
                
while(sum%get!=0){
                    
get--;
                }
            }
        }
        printf(
"%d\n",sum/get);
    }
    
return 0;
}
posted @ 2009-08-23 20:29 未央 閱讀(247) | 評論 (0)編輯 收藏
 

空間點繞任意軸旋轉變換公式

P點繞A向量旋轉θ角后得到P':
P' = Pcosθ + (A × P)sinθ + A(A·P)(1 - cosθ)
注意:視口為向量指向的位置,就是向量指向你,θ為逆時針旋轉的角。
A × P = (Ay*Pz - Az*Py,Az*Px - Ax*Pz,Ax*Py - Ay*Px)

注意:A必須是單位向量

posted @ 2009-08-13 16:24 未央 閱讀(579) | 評論 (0)編輯 收藏
僅列出標題
共8頁: 1 2 3 4 5 6 7 8 
CALENDER
<2011年12月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

常用鏈接

留言簿(6)

隨筆檔案

文章檔案

搜索

  •  

最新評論

閱讀排行榜

評論排行榜


Powered By: 博客園
模板提供滬江博客

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久热精品视频| 亚洲国产天堂久久国产91| 亚洲无玛一区| 一区二区欧美国产| 中文欧美字幕免费| 一区二区三区|亚洲午夜| 亚洲欧洲一区二区三区| 久久久久国产一区二区| 久久久高清一区二区三区| 久久久不卡网国产精品一区| 性欧美1819sex性高清| 欧美与欧洲交xxxx免费观看| 久久久噜久噜久久综合| 久久午夜精品一区二区| 欧美成人免费在线| 亚洲国产免费| 一区二区三区高清在线| 亚洲一区高清| 久久久青草青青国产亚洲免观| 亚洲欧洲日韩在线| 99国产一区| 久久激情五月婷婷| 午夜精品一区二区三区在线视| 久久久久久久久岛国免费| 欧美大秀在线观看| 亚洲一卡久久| 欧美成人黑人xx视频免费观看| 国产精品成人av性教育| 国产婷婷成人久久av免费高清| 亚洲精品日韩综合观看成人91| 亚洲欧美国产视频| 欧美成人自拍| 亚洲欧美文学| 欧美日本在线看| 国产欧美欧洲在线观看| 99国产精品| 欧美fxxxxxx另类| 亚洲伊人观看| 欧美日韩精品免费观看| 在线播放日韩| 久久精品国产一区二区三区免费看| 亚洲免费在线视频| 亚洲黄色精品| 久久久久久久性| 国产精品美女久久久浪潮软件| 亚洲欧洲精品一区二区三区波多野1战4 | 欧美一区二视频在线免费观看| 免费观看成人www动漫视频| 国产精品久久久久三级| 日韩视频一区二区三区在线播放免费观看 | 欧美日韩亚洲一区二区三区| 樱花yy私人影院亚洲| 亚久久调教视频| 亚洲深夜福利| 国产精品jizz在线观看美国| 99国产精品久久久久久久成人热| 欧美+日本+国产+在线a∨观看| 性做久久久久久| 国产欧美一区二区三区久久| 午夜影院日韩| 午夜精品久久久久久99热软件| 欧美午夜片在线免费观看| 在线亚洲欧美视频| 亚洲精品在线二区| 欧美日韩另类国产亚洲欧美一级| 国产精品国产三级国产普通话99| 欧美日韩一区二区三区免费看 | 久久久亚洲影院你懂的| 韩日午夜在线资源一区二区| 久久精品夜夜夜夜久久| 欧美在线免费看| 亚洲第一在线视频| 亚洲国产天堂久久综合网| 欧美成人dvd在线视频| 亚洲免费观看高清在线观看 | 亚洲一区二区日本| 一本一本久久| 国产欧美日韩精品在线| 久久精品在这里| 狂野欧美激情性xxxx| 亚洲国产另类 国产精品国产免费| 免费精品视频| 欧美精品久久久久久久| 亚洲专区国产精品| 欧美一区二区三区久久精品茉莉花 | 欧美xx69| 欧美久久99| 午夜精品视频在线观看一区二区| 欧美一区观看| 亚洲精品婷婷| 亚洲一区二区三区色| 黄色在线一区| 亚洲精品综合精品自拍| 国产日产精品一区二区三区四区的观看方式 | 欧美xx视频| 亚洲一区二区三区在线播放| 欧美一级在线播放| 亚洲美女毛片| 亚洲精品国产系列| 亚洲国产专区校园欧美| 国产亚洲一区二区在线观看| 亚洲国产91精品在线观看| 欧美日韩亚洲一区二区三区在线| 亚洲精品欧美日韩专区| 亚洲欧美一区二区原创| 亚洲精品国产精品国自产观看浪潮| 亚洲精品在线观| 亚洲成人中文| 午夜精品久久久久久99热软件| 最新热久久免费视频| 午夜精品影院| 亚洲一卡二卡三卡四卡五卡| 欧美1区3d| 蜜臀a∨国产成人精品| 国产欧美日韩亚洲精品| 99精品国产99久久久久久福利| 在线观看av一区| 欧美在线视频不卡| 午夜宅男久久久| 欧美性片在线观看| 亚洲精品国产日韩| 亚洲国产欧美在线人成| 久久精品卡一| 久久网站免费| 国产一区欧美| 欧美一区午夜视频在线观看| 欧美影院成人| 国产区日韩欧美| 性久久久久久久久| 久久精品成人一区二区三区| 国产精品免费一区二区三区观看| 亚洲经典在线看| 日韩午夜免费| 欧美女激情福利| 日韩视频一区二区在线观看| 日韩一级精品视频在线观看| 欧美高清视频www夜色资源网| 亚洲第一天堂av| 亚洲免费大片| 国产精品国产三级国产专播精品人| 日韩视频在线免费| 99精品免费网| 欧美偷拍一区二区| 91久久久久久国产精品| 在线亚洲精品| 国产乱子伦一区二区三区国色天香| 夜夜爽www精品| 亚洲男女自偷自拍| 国产丝袜美腿一区二区三区| 欧美在线中文字幕| 美女精品在线观看| 亚洲激精日韩激精欧美精品| 欧美区高清在线| 亚洲无线观看| 久久爱www.| 在线观看日产精品| 欧美二区在线观看| 亚洲丰满少妇videoshd| 一本久道久久久| 国产麻豆一精品一av一免费| 久久国产精品黑丝| 亚洲成人资源| 亚洲一区视频在线观看视频| 欧美久久久久| 亚洲尤物在线视频观看| 亚洲一二三区在线观看| 国产精品永久免费| 免费在线视频一区| 一道本一区二区| 国产精品亚洲一区| 久久久97精品| 亚洲激情成人网| 欧美一区二区三区男人的天堂| 樱桃国产成人精品视频| 欧美日本韩国一区二区三区| 欧美一级免费视频| 亚洲经典三级| 免费成人性网站| 欧美一区二区在线播放| 亚洲精品综合精品自拍| 国产午夜久久| 欧美视频三区在线播放| 久久久久久亚洲综合影院红桃| 亚洲视频播放| 亚洲欧洲精品一区二区| 久久综合久久久久88| 亚洲欧美日韩视频二区| 日韩视频在线一区二区三区| 国内精品久久久久久久果冻传媒| 欧美视频手机在线| 欧美成人有码| 欧美一区二区三区在线视频| 一区二区三区四区精品| 亚洲国产精品久久91精品| 久久影视精品| 久久久久国产精品麻豆ai换脸| 亚洲手机视频| 日韩视频一区二区在线观看 | 国产精品欧美久久| 欧美精品久久99久久在免费线|